Fixed menue for file manager
[public/netxms.git] / src / server / core / np.cpp
CommitLineData
5039dede
AK
1/*
2** NetXMS - Network Management System
496390c2 3** Copyright (C) 2003-2013 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: np.cpp
20**
21**/
22
23#include "nxcore.h"
24
56e92fc9
VK
25/**
26 * Externals
27 */
5039dede
AK
28extern Queue g_nodePollerQueue;
29
56e92fc9
VK
30/**
31 * Discovery class
32 */
5039dede
AK
33class NXSL_DiscoveryClass : public NXSL_Class
34{
35public:
36 NXSL_DiscoveryClass();
37
bb51576f 38 virtual NXSL_Value *getAttr(NXSL_Object *pObject, const TCHAR *pszAttr);
5039dede
AK
39};
40
56e92fc9
VK
41/**
42 * Implementation of discovery class
43 */
7c80f505 44NXSL_DiscoveryClass::NXSL_DiscoveryClass() : NXSL_Class()
5039dede 45{
c42b4551 46 _tcscpy(m_name, _T("NewNode"));
5039dede
AK
47}
48
bb51576f 49NXSL_Value *NXSL_DiscoveryClass::getAttr(NXSL_Object *pObject, const TCHAR *pszAttr)
5039dede
AK
50{
51 DISCOVERY_FILTER_DATA *pData;
52 NXSL_Value *pValue = NULL;
35f836fe 53 TCHAR szBuffer[256];
5039dede 54
bb5365ed 55 pData = (DISCOVERY_FILTER_DATA *)pObject->getData();
35f836fe 56 if (!_tcscmp(pszAttr, _T("ipAddr")))
5039dede
AK
57 {
58 IpToStr(pData->dwIpAddr, szBuffer);
59 pValue = new NXSL_Value(szBuffer);
60 }
35f836fe 61 else if (!_tcscmp(pszAttr, _T("netMask")))
5039dede
AK
62 {
63 IpToStr(pData->dwNetMask, szBuffer);
64 pValue = new NXSL_Value(szBuffer);
65 }
35f836fe 66 else if (!_tcscmp(pszAttr, _T("subnet")))
5039dede
AK
67 {
68 IpToStr(pData->dwSubnetAddr, szBuffer);
69 pValue = new NXSL_Value(szBuffer);
70 }
35f836fe 71 else if (!_tcscmp(pszAttr, _T("isAgent")))
5039dede
AK
72 {
73 pValue = new NXSL_Value((LONG)((pData->dwFlags & NNF_IS_AGENT) ? 1 : 0));
74 }
35f836fe 75 else if (!_tcscmp(pszAttr, _T("isSNMP")))
5039dede
AK
76 {
77 pValue = new NXSL_Value((LONG)((pData->dwFlags & NNF_IS_SNMP) ? 1 : 0));
78 }
35f836fe 79 else if (!_tcscmp(pszAttr, _T("isBridge")))
5039dede
AK
80 {
81 pValue = new NXSL_Value((LONG)((pData->dwFlags & NNF_IS_BRIDGE) ? 1 : 0));
82 }
35f836fe 83 else if (!_tcscmp(pszAttr, _T("isRouter")))
5039dede
AK
84 {
85 pValue = new NXSL_Value((LONG)((pData->dwFlags & NNF_IS_ROUTER) ? 1 : 0));
86 }
35f836fe 87 else if (!_tcscmp(pszAttr, _T("isPrinter")))
5039dede
AK
88 {
89 pValue = new NXSL_Value((LONG)((pData->dwFlags & NNF_IS_PRINTER) ? 1 : 0));
90 }
35f836fe 91 else if (!_tcscmp(pszAttr, _T("isCDP")))
5039dede
AK
92 {
93 pValue = new NXSL_Value((LONG)((pData->dwFlags & NNF_IS_CDP) ? 1 : 0));
94 }
35f836fe 95 else if (!_tcscmp(pszAttr, _T("isSONMP")))
5039dede
AK
96 {
97 pValue = new NXSL_Value((LONG)((pData->dwFlags & NNF_IS_SONMP) ? 1 : 0));
98 }
35f836fe 99 else if (!_tcscmp(pszAttr, _T("isLLDP")))
5039dede
AK
100 {
101 pValue = new NXSL_Value((LONG)((pData->dwFlags & NNF_IS_LLDP) ? 1 : 0));
102 }
35f836fe 103 else if (!_tcscmp(pszAttr, _T("snmpVersion")))
5039dede
AK
104 {
105 pValue = new NXSL_Value((LONG)pData->nSNMPVersion);
106 }
35f836fe 107 else if (!_tcscmp(pszAttr, _T("snmpOID")))
5039dede
AK
108 {
109 pValue = new NXSL_Value(pData->szObjectId);
110 }
35f836fe 111 else if (!_tcscmp(pszAttr, _T("agentVersion")))
5039dede
AK
112 {
113 pValue = new NXSL_Value(pData->szAgentVersion);
114 }
35f836fe 115 else if (!_tcscmp(pszAttr, _T("platformName")))
5039dede
AK
116 {
117 pValue = new NXSL_Value(pData->szPlatform);
118 }
119 return pValue;
120}
121
22d657d2
VK
122/**
123 * Discovery class object
124 */
5039dede
AK
125static NXSL_DiscoveryClass m_nxslDiscoveryClass;
126
22d657d2
VK
127/**
128 * Poll new node for configuration
129 * Returns pointer to new node object on success or NULL on failure
130 *
131 * @param dwIpAddr IP address of new node
132 * @param dwNetMask IP network mask or 0 if not known
133 * @param dwCreationFlags
134 * @param agentPort port number of NetXMS agent
135 * @param snmpPort port number of SNMP agent
136 * @param pszName name for new node, can be NULL
137 * @param dwProxyNode agent proxy node ID or 0 to use direct communications
138 * @param dwSNMPProxy SNMP proxy node ID or 0 to use direct communications
139 * @param pCluster pointer to parent cluster object or NULL
140 * @param zoneId zone ID
141 * @param doConfPoll if set to true, Node::configurationPoll will be called before exit
142 * @param discoveredNode must be set to true if node being added automatically by discovery thread
143 */
967893bb
VK
144Node *PollNewNode(UINT32 dwIpAddr, UINT32 dwNetMask, UINT32 dwCreationFlags,
145 WORD agentPort, WORD snmpPort, const TCHAR *pszName, UINT32 dwProxyNode, UINT32 dwSNMPProxy,
146 Cluster *pCluster, UINT32 zoneId, bool doConfPoll, bool discoveredNode)
5039dede
AK
147{
148 Node *pNode;
35f836fe 149 TCHAR szIpAddr1[32], szIpAddr2[32];
967893bb 150 UINT32 dwFlags = 0;
5039dede 151
dc25b21c 152 DbgPrintf(4, _T("PollNode(%s,%s) zone %d"), IpToStr(dwIpAddr, szIpAddr1), IpToStr(dwNetMask, szIpAddr2), (int)zoneId);
5039dede 153 // Check for node existence
89135050
VK
154 if ((FindNodeByIP(zoneId, dwIpAddr) != NULL) ||
155 (FindSubnetByIP(zoneId, dwIpAddr) != NULL))
5039dede 156 {
c6a32070 157 DbgPrintf(4, _T("PollNode: Node %s already exist in database"), IpToStr(dwIpAddr, szIpAddr1));
5039dede
AK
158 return NULL;
159 }
160
161 if (dwCreationFlags & NXC_NCF_DISABLE_ICMP)
162 dwFlags |= NF_DISABLE_ICMP;
163 if (dwCreationFlags & NXC_NCF_DISABLE_SNMP)
164 dwFlags |= NF_DISABLE_SNMP;
165 if (dwCreationFlags & NXC_NCF_DISABLE_NXCP)
166 dwFlags |= NF_DISABLE_NXCP;
dc25b21c 167 pNode = new Node(dwIpAddr, dwFlags, dwProxyNode, dwSNMPProxy, zoneId);
f1b6417b
VK
168 if (agentPort != 0)
169 pNode->setAgentPort(agentPort);
170 if (snmpPort != 0)
171 pNode->setSnmpPort(snmpPort);
5039dede
AK
172 NetObjInsert(pNode, TRUE);
173 if (pszName != NULL)
eec253a8 174 pNode->setName(pszName);
5039dede 175
a749a70a
VK
176 // Use DNS name as primary name if required
177 if (discoveredNode && ConfigReadInt(_T("UseDNSNameForDiscoveredNodes"), 0))
178 {
967893bb 179 UINT32 ip = htonl(dwIpAddr);
a749a70a
VK
180 struct hostent *hs = gethostbyaddr((char *)&ip, 4, AF_INET);
181 if (hs != NULL)
182 {
183 TCHAR dnsName[MAX_DNS_NAME];
184#ifdef UNICODE
185 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, hs->h_name, -1, dnsName, MAX_DNS_NAME);
186 dnsName[MAX_DNS_NAME - 1] = 0;
187#else
188 nx_strncpy(dnsName, hs->h_name, MAX_DNS_NAME);
189#endif
190 if (ntohl(ResolveHostName(dnsName)) == dwIpAddr)
191 {
192 // We have valid DNS name which resolves back to node's IP address, use it as primary name
193 pNode->setPrimaryName(dnsName);
194 DbgPrintf(4, _T("PollNode: Using DNS name %s as primary name for node %s"), dnsName, IpToStr(dwIpAddr, szIpAddr1));
195 }
196 }
197 }
198
5039dede
AK
199 // Bind node to cluster before first configuration poll
200 if (pCluster != NULL)
201 {
6fd6de0a 202 pCluster->applyToTarget(pNode);
5039dede
AK
203 }
204
205 if (dwCreationFlags & NXC_NCF_CREATE_UNMANAGED)
206 {
eec253a8 207 pNode->setMgmtStatus(FALSE);
72e97d1c 208 pNode->checkSubnetBinding(NULL);
5039dede 209 }
5039dede
AK
210
211 // Add default DCIs
f05a8a45
VK
212 pNode->addDCObject(new DCItem(CreateUniqueId(IDG_ITEM), _T("Status"), DS_INTERNAL, DCI_DT_INT,
213 ConfigReadInt(_T("DefaultDCIPollingInterval"), 60),
214 ConfigReadInt(_T("DefaultDCIRetentionTime"), 30), pNode));
588f7351
VK
215
216 if (doConfPoll)
217 pNode->configurationPoll(NULL, 0, -1, dwNetMask);
218
219 pNode->unhide();
c42b4551 220 PostEvent(EVENT_NODE_ADDED, pNode->getId(), "d", (int)(discoveredNode ? 1 : 0));
588f7351 221
5039dede
AK
222 return pNode;
223}
224
22d657d2
VK
225/**
226 * Find existing node by MAC address to detect IP address change for already known node.
227 *
228 * @param dwIpAddr new (discovered) IP address
229 * @param dwNetMask network mask for new address
230 * @param dwZoneID zone ID
231 * @param bMacAddr MAC address of discovered node, or NULL if not known
232 *
233 * @return pointer to existing interface object with given MAC address or NULL if no such interface found
234 */
967893bb 235static Interface *GetOldNodeWithNewIP(UINT32 dwIpAddr, UINT32 dwNetMask, UINT32 dwZoneId, BYTE *bMacAddr)
baa5324c
AK
236{
237 Subnet *subnet;
238 BYTE nodeMacAddr[MAC_ADDR_LENGTH];
239 TCHAR szIpAddr[16], szMacAddr[20];
240
241 IpToStr(dwIpAddr, szIpAddr);
242 MACToStr(bMacAddr, szMacAddr);
243 DbgPrintf(6, _T("GetOldNodeWithNewIP: ip=%s mac=%s"), szIpAddr, szMacAddr);
244
245 if (bMacAddr == NULL)
246 {
9075806c 247 subnet = FindSubnetForNode(dwZoneId, dwIpAddr);
baa5324c
AK
248 if (subnet != NULL)
249 {
250 BOOL found = subnet->findMacAddress(dwIpAddr, nodeMacAddr);
251 if (!found)
252 {
22d657d2 253 DbgPrintf(6, _T("GetOldNodeWithNewIP: MAC address not found"));
baa5324c
AK
254 return NULL;
255 }
256 }
22d657d2
VK
257 else
258 {
259 DbgPrintf(6, _T("GetOldNodeWithNewIP: subnet not found"));
260 return NULL;
261 }
baa5324c
AK
262 }
263 else
264 {
265 memcpy(nodeMacAddr, bMacAddr, MAC_ADDR_LENGTH);
266 }
267
22d657d2 268 Interface *iface = FindInterfaceByMAC(nodeMacAddr);
baa5324c 269
22d657d2
VK
270 if (iface == NULL)
271 DbgPrintf(6, _T("GetOldNodeWithNewIP: returning null (FindInterfaceByMAC!)"));
baa5324c 272
22d657d2 273 return iface;
baa5324c 274}
5039dede 275
5db0d494
VK
276/**
277 * Check if host at given IP address is reachable by NetXMS server
278 */
967893bb 279static bool HostIsReachable(UINT32 ipAddr, UINT32 zoneId, bool fullCheck, SNMP_Transport **transport, AgentConnection **agentConn)
5db0d494
VK
280{
281 bool reachable = false;
282
283 if (transport != NULL)
284 *transport = NULL;
285 if (agentConn != NULL)
286 *agentConn = NULL;
287
967893bb
VK
288 UINT32 agentProxy = 0;
289 UINT32 icmpProxy = 0;
290 UINT32 snmpProxy = 0;
5db0d494
VK
291
292 if (IsZoningEnabled() && (zoneId != 0))
293 {
294 Zone *zone = (Zone *)g_idxZoneByGUID.get(zoneId);
295 if (zone != NULL)
296 {
297 agentProxy = zone->getAgentProxy();
298 icmpProxy = zone->getIcmpProxy();
299 snmpProxy = zone->getSnmpProxy();
300 }
301 }
302
303 // *** ICMP PING ***
304 if (icmpProxy != 0)
305 {
306 Node *proxyNode = (Node *)g_idxNodeById.get(icmpProxy);
307 if ((proxyNode != NULL) && proxyNode->isNativeAgent() && !proxyNode->isDown())
308 {
309 AgentConnection *conn = proxyNode->createAgentConnection();
310 if (conn != NULL)
311 {
312 TCHAR parameter[64], buffer[64];
313
314 _sntprintf(parameter, 64, _T("Icmp.Ping(%s)"), IpToStr(ipAddr, buffer));
315 if (conn->getParameter(parameter, 64, buffer) == ERR_SUCCESS)
316 {
317 TCHAR *eptr;
318 long value = _tcstol(buffer, &eptr, 10);
319 if ((*eptr == 0) && (value >= 0))
320 {
321 if (value < 10000)
322 {
323 reachable = true;
324 }
325 }
326 }
327 conn->disconnect();
328 delete conn;
329 }
330 }
331 }
332 else // not using ICMP proxy
333 {
c59466d2 334 if (IcmpPing(htonl(ipAddr), 3, g_icmpPingTimeout, NULL, g_icmpPingSize) == ICMP_SUCCESS)
5db0d494
VK
335 reachable = true;
336 }
337
338 if (reachable && !fullCheck)
339 return true;
340
341 // *** NetXMS agent ***
1938d609 342 AgentConnection *pAgentConn = new AgentConnectionEx(0, htonl(ipAddr), AGENT_LISTEN_PORT, AUTH_NONE, _T(""));
5db0d494
VK
343 if (agentProxy != 0)
344 {
345 Node *proxyNode = (Node *)g_idxNodeById.get(agentProxy);
346 if (proxyNode != NULL)
347 {
348 pAgentConn->setProxy(htonl(proxyNode->IpAddr()), proxyNode->getAgentPort(),
c42b4551 349 proxyNode->getAgentAuthMethod(), proxyNode->getSharedSecret());
5db0d494
VK
350 }
351 }
1938d609
VK
352 UINT32 rcc;
353 if (!pAgentConn->connect(g_pServerKey, FALSE, &rcc))
354 {
355 // If there are authentication problem, try default shared secret
356 if ((rcc == ERR_AUTH_REQUIRED) || (rcc == ERR_AUTH_FAILED))
357 {
358 TCHAR secret[MAX_SECRET_LENGTH];
359 ConfigReadStr(_T("AgentDefaultSharedSecret"), secret, MAX_SECRET_LENGTH, _T("netxms"));
360 pAgentConn->setAuthData(AUTH_SHA1_HASH, secret);
361 pAgentConn->connect(g_pServerKey, FALSE, &rcc);
362 }
363 }
364 if (rcc == ERR_SUCCESS)
5db0d494
VK
365 {
366 if (agentConn != NULL)
367 {
368 *agentConn = pAgentConn;
369 pAgentConn = NULL; // prevent deletion
370 }
371 reachable = true;
372 }
373 delete pAgentConn;
374
375 if (reachable && !fullCheck)
376 return true;
377
378 // *** SNMP ***
a7189bdd 379 SNMP_Transport *pTransport = NULL;
5db0d494
VK
380 if (snmpProxy != 0)
381 {
382 Node *proxyNode = (Node *)g_idxNodeById.get(snmpProxy);
383 if (proxyNode != NULL)
384 {
385 AgentConnection *pConn;
386
387 pConn = proxyNode->createAgentConnection();
388 if (pConn != NULL)
389 {
390 pTransport = new SNMP_ProxyTransport(pConn, ipAddr, 161);
391 }
392 }
393 }
394 else
395 {
396 pTransport = new SNMP_UDPTransport;
397 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(ipAddr), 161);
398 }
a7189bdd
VK
399 if (pTransport != NULL)
400 {
401 int version;
402 StringList oids;
403 oids.add(_T(".1.3.6.1.2.1.1.2.0"));
404 oids.add(_T(".1.3.6.1.2.1.1.1.0"));
405 AddDriverSpecificOids(&oids);
406 SNMP_SecurityContext *ctx = SnmpCheckCommSettings(pTransport, &version, NULL, &oids);
407 if (ctx != NULL)
408 {
409 delete ctx;
410 if (transport != NULL)
411 {
412 pTransport->setSnmpVersion(version);
413 *transport = pTransport;
414 pTransport = NULL; // prevent deletion
415 }
416 reachable = true;
417 }
418 delete pTransport;
419 }
5db0d494
VK
420
421 return reachable;
422}
423
22d657d2
VK
424/**
425 * Check if newly discovered node should be added
426 */
967893bb 427static BOOL AcceptNewNode(UINT32 dwIpAddr, UINT32 dwNetMask, UINT32 zoneId, BYTE *macAddr)
5039dede
AK
428{
429 DISCOVERY_FILTER_DATA data;
df8a4ca2 430 TCHAR szFilter[MAX_DB_STRING], szBuffer[256], szIpAddr[16];
967893bb 431 UINT32 dwTemp;
5039dede 432 AgentConnection *pAgentConn;
5039dede 433 BOOL bResult = FALSE;
5db0d494 434 SNMP_Transport *pTransport;
5039dede
AK
435
436 IpToStr(dwIpAddr, szIpAddr);
89135050
VK
437 if ((FindNodeByIP(zoneId, dwIpAddr) != NULL) ||
438 (FindSubnetByIP(zoneId, dwIpAddr) != NULL))
5039dede 439 {
35f836fe 440 DbgPrintf(4, _T("AcceptNewNode(%s): node already exist in database"), szIpAddr);
5039dede
AK
441 return FALSE; // Node already exist in database
442 }
443
a5c8431d
VK
444 if (!memcmp(macAddr, "\xFF\xFF\xFF\xFF\xFF\xFF", 6))
445 {
446 DbgPrintf(4, _T("AcceptNewNode(%s): broadcast MAC address"), szIpAddr);
447 return FALSE; // Broadcast MAC
448 }
449
22d657d2
VK
450 Interface *iface = GetOldNodeWithNewIP(dwIpAddr, dwNetMask, zoneId, macAddr);
451 if (iface != NULL)
baa5324c 452 {
5db0d494
VK
453 if (!HostIsReachable(dwIpAddr, zoneId, false, NULL, NULL))
454 {
455 DbgPrintf(4, _T("AcceptNewNode(%s): found existing interface with same MAC address, but new IP is not reachable"), szIpAddr);
456 return FALSE;
457 }
458
22d657d2
VK
459 Node *oldNode = iface->getParentNode();
460 if (iface->IpAddr() == oldNode->IpAddr())
461 {
462 // we should change node's primary IP only if old IP for this MAC was also node's primary IP
463 TCHAR szOldIpAddr[16];
464 IpToStr(oldNode->IpAddr(), szOldIpAddr);
465 DbgPrintf(4, _T("AcceptNewNode(%s): node already exist in database with ip %s, will change to new"),
466 szIpAddr, szOldIpAddr);
467 oldNode->changeIPAddress(dwIpAddr);
468 }
baa5324c
AK
469 return FALSE;
470 }
471
496390c2 472 // Allow filtering by loaded modules
967893bb 473 for(UINT32 i = 0; i < g_dwNumModules; i++)
496390c2
VK
474 {
475 if (g_pModuleList[i].pfAcceptNewNode != NULL)
476 {
477 if (!g_pModuleList[i].pfAcceptNewNode(dwIpAddr, dwNetMask, zoneId, macAddr))
478 return FALSE; // filtered out by module
479 }
480 }
481
5039dede 482 // Read configuration
35f836fe 483 ConfigReadStr(_T("DiscoveryFilter"), szFilter, MAX_DB_STRING, _T(""));
5039dede
AK
484 StrStrip(szFilter);
485
56e92fc9 486 // Check for filter script
35f836fe 487 if ((szFilter[0] == 0) || (!_tcsicmp(szFilter, _T("none"))))
5039dede 488 {
5db0d494
VK
489 if (!HostIsReachable(dwIpAddr, zoneId, false, NULL, NULL))
490 {
491 DbgPrintf(4, _T("AcceptNewNode(%s): host is not reachable"), szIpAddr);
492 return FALSE;
493 }
35f836fe 494 DbgPrintf(4, _T("AcceptNewNode(%s): no filtering, node accepted"), szIpAddr);
5039dede
AK
495 return TRUE; // No filtering
496 }
497
498 // Initialize new node data
499 memset(&data, 0, sizeof(DISCOVERY_FILTER_DATA));
500 data.dwIpAddr = dwIpAddr;
501 data.dwNetMask = dwNetMask;
502 data.dwSubnetAddr = dwIpAddr & dwNetMask;
503
56e92fc9 504 // Check for address range if we use simple filter instead of script
967893bb 505 UINT32 autoFilterFlags;
56e92fc9
VK
506 if (!_tcsicmp(szFilter, _T("auto")))
507 {
508 autoFilterFlags = ConfigReadULong(_T("DiscoveryFilterFlags"), DFF_ALLOW_AGENT | DFF_ALLOW_SNMP);
509 DbgPrintf(4, _T("AcceptNewNode(%s): auto filter, flags=%04X"), szIpAddr, autoFilterFlags);
510
511 if (autoFilterFlags & DFF_ONLY_RANGE)
512 {
513 DbgPrintf(4, _T("AcceptNewNode(%s): auto filter - checking range"), szIpAddr);
514 DB_RESULT hResult = DBSelect(g_hCoreDB, _T("SELECT addr_type,addr1,addr2 FROM address_lists WHERE list_type=2"));
515 if (hResult != NULL)
516 {
517 int nRows = DBGetNumRows(hResult);
518 for(int i = 0; (i < nRows) && (!bResult); i++)
519 {
520 int nType = DBGetFieldLong(hResult, i, 0);
521 if (nType == 0)
522 {
523 // Subnet
524 bResult = (data.dwIpAddr & DBGetFieldIPAddr(hResult, i, 2)) == DBGetFieldIPAddr(hResult, i, 1);
525 }
526 else
527 {
528 // Range
529 bResult = ((data.dwIpAddr >= DBGetFieldIPAddr(hResult, i, 1)) &&
530 (data.dwIpAddr <= DBGetFieldIPAddr(hResult, i, 2)));
531 }
532 }
533 DBFreeResult(hResult);
534 }
3b71dbbb
VK
535 DbgPrintf(4, _T("AcceptNewNode(%s): auto filter - range check result is %d"), szIpAddr, bResult);
536 if (!bResult)
537 return FALSE;
56e92fc9 538 }
56e92fc9
VK
539 }
540
5db0d494
VK
541 // Check if host is reachable
542 if (!HostIsReachable(dwIpAddr, zoneId, true, &pTransport, &pAgentConn))
543 {
544 DbgPrintf(4, _T("AcceptNewNode(%s): host is not reachable"), szIpAddr);
545 return FALSE;
546 }
547 if (pTransport != NULL)
5039dede
AK
548 {
549 data.dwFlags |= NNF_IS_SNMP;
5db0d494 550 data.nSNMPVersion = pTransport->getSnmpVersion();
5039dede 551 }
5db0d494 552 if (pAgentConn != NULL)
5039dede
AK
553 {
554 data.dwFlags |= NNF_IS_AGENT;
4687826e
VK
555 pAgentConn->getParameter(_T("Agent.Version"), MAX_AGENT_VERSION_LEN, data.szAgentVersion);
556 pAgentConn->getParameter(_T("System.PlatformName"), MAX_PLATFORM_NAME_LEN, data.szPlatform);
5039dede
AK
557 }
558
559 // Check if node is a router
560 if (data.dwFlags & NNF_IS_SNMP)
561 {
5d2c5741 562 if (SnmpGet(data.nSNMPVersion, pTransport,
967893bb 563 _T(".1.3.6.1.2.1.4.1.0"), NULL, 0, &dwTemp, sizeof(UINT32), 0) == SNMP_ERR_SUCCESS)
5039dede
AK
564 {
565 if (dwTemp == 1)
566 data.dwFlags |= NNF_IS_ROUTER;
567 }
568 }
569 else if (data.dwFlags & NNF_IS_AGENT)
570 {
571 // Check IP forwarding status
4687826e 572 if (pAgentConn->getParameter(_T("Net.IP.Forwarding"), 16, szBuffer) == ERR_SUCCESS)
5039dede
AK
573 {
574 if (_tcstoul(szBuffer, NULL, 10) != 0)
575 data.dwFlags |= NNF_IS_ROUTER;
576 }
577 }
578
579 // Check various SNMP device capabilities
580 if (data.dwFlags & NNF_IS_SNMP)
581 {
582 // Get SNMP OID
5d2c5741 583 SnmpGet(data.nSNMPVersion, pTransport,
f42b8099 584 _T(".1.3.6.1.2.1.1.2.0"), NULL, 0, data.szObjectId, MAX_OID_LEN * 4, 0);
5039dede
AK
585
586 // Check if node is a bridge
5d2c5741 587 if (SnmpGet(data.nSNMPVersion, pTransport,
d525c9ed 588 _T(".1.3.6.1.2.1.17.1.1.0"), NULL, 0, szBuffer, sizeof(szBuffer), 0) == SNMP_ERR_SUCCESS)
5039dede
AK
589 {
590 data.dwFlags |= NNF_IS_BRIDGE;
591 }
592
593 // Check for CDP (Cisco Discovery Protocol) support
5d2c5741 594 if (SnmpGet(data.nSNMPVersion, pTransport,
967893bb 595 _T(".1.3.6.1.4.1.9.9.23.1.3.1.0"), NULL, 0, &dwTemp, sizeof(UINT32), 0) == SNMP_ERR_SUCCESS)
5039dede
AK
596 {
597 if (dwTemp == 1)
598 data.dwFlags |= NNF_IS_CDP;
599 }
600
601 // Check for SONMP (Nortel topology discovery protocol) support
5d2c5741 602 if (SnmpGet(data.nSNMPVersion, pTransport,
967893bb 603 _T(".1.3.6.1.4.1.45.1.6.13.1.2.0"), NULL, 0, &dwTemp, sizeof(UINT32), 0) == SNMP_ERR_SUCCESS)
5039dede
AK
604 {
605 if (dwTemp == 1)
606 data.dwFlags |= NNF_IS_SONMP;
607 }
608
609 // Check for LLDP (Link Layer Discovery Protocol) support
5d2c5741 610 if (SnmpGet(data.nSNMPVersion, pTransport,
d525c9ed 611 _T(".1.0.8802.1.1.2.1.3.2.0"), NULL, 0, szBuffer, sizeof(szBuffer), 0) == SNMP_ERR_SUCCESS)
5039dede
AK
612 {
613 data.dwFlags |= NNF_IS_LLDP;
614 }
615 }
616
617 // Cleanup
618 delete pAgentConn;
619 delete pTransport;
620
621 // Check if we use simple filter instead of script
35f836fe 622 if (!_tcsicmp(szFilter, _T("auto")))
5039dede 623 {
56e92fc9
VK
624 bResult = FALSE;
625 if ((autoFilterFlags & (DFF_ALLOW_AGENT | DFF_ALLOW_SNMP)) == 0)
5039dede
AK
626 {
627 bResult = TRUE;
628 }
629 else
630 {
56e92fc9 631 if (autoFilterFlags & DFF_ALLOW_AGENT)
5039dede
AK
632 {
633 if (data.dwFlags & NNF_IS_AGENT)
634 bResult = TRUE;
635 }
636
56e92fc9 637 if (autoFilterFlags & DFF_ALLOW_SNMP)
5039dede
AK
638 {
639 if (data.dwFlags & NNF_IS_SNMP)
640 bResult = TRUE;
641 }
642 }
35f836fe 643 DbgPrintf(4, _T("AcceptNewNode(%s): auto filter - bResult=%d"), szIpAddr, bResult);
5039dede
AK
644 }
645 else
646 {
6b29839d
VK
647 NXSL_VM *vm = g_pScriptLibrary->createVM(szFilter, new NXSL_ServerEnv);
648 if (vm != NULL)
5039dede 649 {
35f836fe 650 DbgPrintf(4, _T("AcceptNewNode(%s): Running filter script %s"), szIpAddr, szFilter);
6b29839d
VK
651 NXSL_Value *pValue = new NXSL_Value(new NXSL_Object(&m_nxslDiscoveryClass, &data));
652 if (vm->run(1, &pValue))
5039dede 653 {
6b29839d 654 bResult = (vm->getResult()->getValueAsInt32() != 0) ? TRUE : FALSE;
35f836fe 655 DbgPrintf(4, _T("AcceptNewNode(%s): Filter script result: %d"), szIpAddr, bResult);
5039dede
AK
656 }
657 else
658 {
35f836fe 659 DbgPrintf(4, _T("AcceptNewNode(%s): Filter script execution error: %s"),
6b29839d
VK
660 szIpAddr, vm->getErrorText());
661 PostEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, "ssd", szFilter, vm->getErrorText(), 0);
5039dede 662 }
6b29839d 663 delete vm;
5039dede
AK
664 }
665 else
666 {
35f836fe 667 DbgPrintf(4, _T("AcceptNewNode(%s): Cannot find filter script %s"), szIpAddr, szFilter);
5039dede 668 }
5039dede
AK
669 }
670
671 return bResult;
672}
673
496390c2
VK
674/**
675 * Node poller thread (poll new nodes and put them into the database)
676 */
5039dede
AK
677THREAD_RESULT THREAD_CALL NodePoller(void *arg)
678{
679 NEW_NODE *pInfo;
680 TCHAR szIpAddr[16], szNetMask[16];
681
35f836fe 682 DbgPrintf(1, _T("Node poller started"));
5039dede 683
89135050 684 while(!IsShutdownInProgress())
5039dede
AK
685 {
686 pInfo = (NEW_NODE *)g_nodePollerQueue.GetOrBlock();
687 if (pInfo == INVALID_POINTER_VALUE)
688 break; // Shutdown indicator received
689
dc25b21c
VK
690 DbgPrintf(4, _T("NodePoller: processing node %s/%s in zone %d"),
691 IpToStr(pInfo->dwIpAddr, szIpAddr), IpToStr(pInfo->dwNetMask, szNetMask), (int)pInfo->zoneId);
e02953a4 692 if (pInfo->ignoreFilter || AcceptNewNode(pInfo->dwIpAddr, pInfo->dwNetMask, pInfo->zoneId, pInfo->bMacAddr))
07f6978d 693 {
ff6d2c5d
VK
694 ObjectTransactionStart();
695 PollNewNode(pInfo->dwIpAddr, pInfo->dwNetMask, 0, 0, 0, NULL, 0, 0, NULL, pInfo->zoneId, true, true);
696 ObjectTransactionEnd();
07f6978d 697 }
5039dede
AK
698 free(pInfo);
699 }
35f836fe 700 DbgPrintf(1, _T("Node poller thread terminated"));
5039dede
AK
701 return THREAD_OK;
702}