added NXSL function AgentExecuteAction
[public/netxms.git] / src / server / core / nxslext.cpp
CommitLineData
aa28fcea 1/*
5039dede 2** NetXMS - Network Management System
297a88eb 3** Copyright (C) 2003-2016 Raden Solutions
5039dede
AK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: nxslext.cpp
20**
21**/
22
23#include "nxcore.h"
24
fdbee7f8
VK
25/**
26 * Externals
27 */
967893bb 28extern UINT32 g_nxslNumSituationFunctions;
4d0c32f3
VK
29extern NXSL_ExtFunction g_nxslSituationFunctions[];
30
5039dede 31void RegisterDCIFunctions(NXSL_Environment *pEnv);
24a5d5ab
VK
32int F_map(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
33int F_mapList(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
5039dede 34
459f4057
VK
35int F_FindAlarmById(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
36int F_FindAlarmByKey(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
37
fdbee7f8
VK
38/**
39 * Get node's custom attribute
40 * First argument is a node object, and second is an attribute name
41 */
6b29839d 42static int F_GetCustomAttribute(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
5039dede
AK
43{
44 NXSL_Object *object;
5039dede
AK
45 const TCHAR *value;
46
bb5365ed 47 if (!argv[0]->isObject())
5039dede
AK
48 return NXSL_ERR_NOT_OBJECT;
49
bb5365ed 50 if (!argv[1]->isString())
5039dede
AK
51 return NXSL_ERR_NOT_STRING;
52
bb5365ed 53 object = argv[0]->getValueAsObject();
84a815cd
VK
54 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
55 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
99030539
Z
56 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
57 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
58 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
5039dede
AK
59 return NXSL_ERR_BAD_CLASS;
60
84a815cd
VK
61 NetObj *netxmsObject = (NetObj *)object->getData();
62 value = netxmsObject->getCustomAttribute(argv[1]->getValueAsCString());
5039dede
AK
63 if (value != NULL)
64 {
65 *ppResult = new NXSL_Value(value);
66 }
67 else
68 {
9daff89d 69 *ppResult = new NXSL_Value; // Return NULL if attribute not found
5039dede
AK
70 }
71
72 return 0;
73}
74
fdbee7f8
VK
75/**
76 * Set node's custom attribute
77 * First argument is a node object, second is an attribute name, third is new value
78 * Returns previous value
79 */
6b29839d 80static int F_SetCustomAttribute(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
9daff89d
VK
81{
82 NXSL_Object *object;
9daff89d
VK
83 const TCHAR *value;
84
85 if (!argv[0]->isObject())
86 return NXSL_ERR_NOT_OBJECT;
87
88 if (!argv[1]->isString() || !argv[2]->isString())
89 return NXSL_ERR_NOT_STRING;
90
91 object = argv[0]->getValueAsObject();
84a815cd
VK
92 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
93 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
99030539
Z
94 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
95 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
96 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
9daff89d
VK
97 return NXSL_ERR_BAD_CLASS;
98
84a815cd
VK
99 NetObj *netxmsObject = (NetObj *)object->getData();
100 value = netxmsObject->getCustomAttribute(argv[1]->getValueAsCString());
9daff89d
VK
101 if (value != NULL)
102 {
103 *ppResult = new NXSL_Value(value);
104 }
105 else
106 {
107 *ppResult = new NXSL_Value; // Return NULL if attribute not found
108 }
109
84a815cd 110 netxmsObject->setCustomAttribute(argv[1]->getValueAsCString(), argv[2]->getValueAsCString());
9daff89d
VK
111
112 return 0;
113}
114
aa28fcea 115/**
116 * Delete node's custom attribute
117 * First argument is a node object, second is an attribute name
118 */
119static int F_DeleteCustomAttribute(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
120{
121 NXSL_Object *object;
aa28fcea 122
123 if (!argv[0]->isObject())
124 return NXSL_ERR_NOT_OBJECT;
125
126 if (!argv[1]->isString())
127 return NXSL_ERR_NOT_STRING;
128
129 object = argv[0]->getValueAsObject();
130 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
131 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
99030539
Z
132 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
133 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
134 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
aa28fcea 135 return NXSL_ERR_BAD_CLASS;
136
137 NetObj *netxmsObject = (NetObj *)object->getData();
138 netxmsObject->deleteCustomAttribute(argv[1]->getValueAsCString());
139 *ppResult = new NXSL_Value;
140 return 0;
141}
142
4dd963e9
VK
143/**
144 * Get interface name by index
145 * Parameters: node object and interface index
146 */
6b29839d 147static int F_GetInterfaceName(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
6422b9bb 148{
bb5365ed 149 if (!argv[0]->isObject())
6422b9bb
VK
150 return NXSL_ERR_NOT_OBJECT;
151
bb5365ed 152 if (!argv[1]->isInteger())
6422b9bb
VK
153 return NXSL_ERR_NOT_INTEGER;
154
bb5365ed 155 NXSL_Object *object = argv[0]->getValueAsObject();
906093fa 156 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
6422b9bb
VK
157 return NXSL_ERR_BAD_CLASS;
158
bb5365ed 159 Node *node = (Node *)object->getData();
c75e9ee4 160 Interface *ifc = node->findInterfaceByIndex(argv[1]->getValueAsUInt32());
6422b9bb
VK
161 if (ifc != NULL)
162 {
c42b4551 163 *ppResult = new NXSL_Value(ifc->getName());
6422b9bb
VK
164 }
165 else
166 {
167 *ppResult = new NXSL_Value; // Return NULL if interface not found
168 }
169
170 return 0;
171}
172
4dd963e9
VK
173/**
174 * Get interface object by index
175 * Parameters: node object and interface index
176 */
6b29839d 177static int F_GetInterfaceObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
09e834a1
VK
178{
179 if (!argv[0]->isObject())
180 return NXSL_ERR_NOT_OBJECT;
181
182 if (!argv[1]->isInteger())
183 return NXSL_ERR_NOT_INTEGER;
184
185 NXSL_Object *object = argv[0]->getValueAsObject();
186 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
187 return NXSL_ERR_BAD_CLASS;
188
189 Node *node = (Node *)object->getData();
c75e9ee4 190 Interface *ifc = node->findInterfaceByIndex(argv[1]->getValueAsUInt32());
09e834a1
VK
191 if (ifc != NULL)
192 {
193 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslInterfaceClass, ifc));
194 }
195 else
196 {
197 *ppResult = new NXSL_Value; // Return NULL if interface not found
198 }
199
200 return 0;
201}
202
4dd963e9
VK
203/**
204 * Find node object
205 * First argument: current node object or null
206 * Second argument: node id or name
207 * Returns node object or null if requested node was not found or access to it was denied
208 */
6b29839d 209static int F_FindNodeObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
906093fa
VK
210{
211 Node *currNode = NULL, *node = NULL;
212
213 if (!argv[0]->isNull())
214 {
215 if (!argv[0]->isObject())
216 return NXSL_ERR_NOT_OBJECT;
217
218 NXSL_Object *object = argv[0]->getValueAsObject();
219 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
220 return NXSL_ERR_BAD_CLASS;
221
222 currNode = (Node *)object->getData();
223 }
224
225 if (!argv[1]->isString())
226 return NXSL_ERR_NOT_STRING;
227
228 if (argv[1]->isInteger())
229 {
230 NetObj *o = FindObjectById(argv[1]->getValueAsUInt32());
c42b4551 231 if ((o != NULL) && (o->getObjectClass() == OBJECT_NODE))
906093fa
VK
232 node = (Node *)o;
233 }
234 else
235 {
236 node = (Node *)FindObjectByName(argv[1]->getValueAsCString(), OBJECT_NODE);
237 }
238
239 if (node != NULL)
240 {
c8076b19 241 if (g_flags & AF_CHECK_TRUSTED_NODES)
906093fa 242 {
c42b4551 243 if ((currNode != NULL) && (node->isTrustedNode(currNode->getId())))
906093fa
VK
244 {
245 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, node));
246 }
247 else
248 {
249 // No access, return null
250 *ppResult = new NXSL_Value;
3d6142ef 251 DbgPrintf(4, _T("NXSL::FindNodeObject(%s [%d], '%s'): access denied for node %s [%d]"),
c42b4551
VK
252 (currNode != NULL) ? currNode->getName() : _T("null"), (currNode != NULL) ? currNode->getId() : 0,
253 argv[1]->getValueAsCString(), node->getName(), node->getId());
906093fa
VK
254 }
255 }
256 else
257 {
258 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, node));
259 }
260 }
261 else
262 {
263 // Node not found, return null
264 *ppResult = new NXSL_Value;
265 }
266
267 return 0;
268}
269
4dd963e9
VK
270/**
271 * Find object
272 * First argument: object id or name
273 * Second argument (optional): current node object or null
274 * Returns generic object or null if requested object was not found or access to it was denied
275 */
6b29839d 276static int F_FindObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
58190c34
VK
277{
278 NetObj *object = NULL;
279
280 if ((argc !=1) && (argc != 2))
281 return NXSL_ERR_INVALID_ARGUMENT_COUNT;
282
283 if (!argv[0]->isString())
284 return NXSL_ERR_NOT_STRING;
285
edad83db 286 if (argc == 2 && (!argv[1]->isNull() && !argv[1]->isObject()))
58190c34
VK
287 return NXSL_ERR_NOT_OBJECT;
288
289 if (argv[0]->isInteger())
290 {
291 object = FindObjectById(argv[0]->getValueAsUInt32());
292 }
293 else
294 {
a32a63c8 295 object = FindObjectByName(argv[0]->getValueAsCString(), -1);
58190c34
VK
296 }
297
298 if (object != NULL)
299 {
c8076b19 300 if (g_flags & AF_CHECK_TRUSTED_NODES)
58190c34
VK
301 {
302 Node *currNode = NULL;
303 if ((argc == 2) && !argv[1]->isNull())
304 {
305 NXSL_Object *o = argv[1]->getValueAsObject();
306 if (_tcscmp(o->getClass()->getName(), g_nxslNodeClass.getName()))
307 return NXSL_ERR_BAD_CLASS;
308
309 currNode = (Node *)o->getData();
310 }
c42b4551 311 if ((currNode != NULL) && (object->isTrustedNode(currNode->getId())))
58190c34 312 {
99030539 313 *ppResult = object->createNXSLObject();
58190c34
VK
314 }
315 else
316 {
317 // No access, return null
318 *ppResult = new NXSL_Value;
319 DbgPrintf(4, _T("NXSL::FindObject('%s', %s [%d]): access denied for node %s [%d]"),
320 argv[0]->getValueAsCString(),
c42b4551
VK
321 (currNode != NULL) ? currNode->getName() : _T("null"), (currNode != NULL) ? currNode->getId() : 0,
322 object->getName(), object->getId());
58190c34
VK
323 }
324 }
325 else
326 {
99030539 327 *ppResult = object->createNXSLObject();;
58190c34
VK
328 }
329 }
330 else
331 {
332 // Object not found, return null
333 *ppResult = new NXSL_Value;
334 }
335
336 return 0;
337}
338
4dd963e9
VK
339/**
340 * Get node object's parents
341 * First argument: node object
342 * Returns array of accessible parent objects
343 */
6b29839d 344static int F_GetNodeParents(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
501b7b03
VK
345{
346 if (!argv[0]->isObject())
347 return NXSL_ERR_NOT_OBJECT;
348
349 NXSL_Object *object = argv[0]->getValueAsObject();
350 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
351 return NXSL_ERR_BAD_CLASS;
352
353 Node *node = (Node *)object->getData();
354 *ppResult = new NXSL_Value(node->getParentsForNXSL());
355 return 0;
356}
357
0ae82278
VK
358/**
359 * Get node object's templates
360 * First argument: node object
361 * Returns array of accessible template objects
362 */
363static int F_GetNodeTemplates(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
364{
365 if (!argv[0]->isObject())
366 return NXSL_ERR_NOT_OBJECT;
367
368 NXSL_Object *object = argv[0]->getValueAsObject();
369 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
370 return NXSL_ERR_BAD_CLASS;
371
372 Node *node = (Node *)object->getData();
373 *ppResult = new NXSL_Value(node->getTemplatesForNXSL());
374 return 0;
375}
376
4dd963e9
VK
377/**
378 * Get object's parents
379 * First argument: NetXMS object (NetObj, Node, or Interface)
380 * Returns array of accessible parent objects
381 */
6b29839d 382static int F_GetObjectParents(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
06c104c6
VK
383{
384 if (!argv[0]->isObject())
385 return NXSL_ERR_NOT_OBJECT;
386
387 NXSL_Object *object = argv[0]->getValueAsObject();
388 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
389 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
99030539
Z
390 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
391 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
392 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
06c104c6
VK
393 return NXSL_ERR_BAD_CLASS;
394
395 NetObj *netobj = (NetObj *)object->getData();
396 *ppResult = new NXSL_Value(netobj->getParentsForNXSL());
397 return 0;
398}
399
4dd963e9
VK
400/**
401 * Get object's children
402 * First argument: NetXMS object (NetObj, Node, or Interface)
403 * Returns array of accessible child objects
404 */
6b29839d 405static int F_GetObjectChildren(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
d679defa
VK
406{
407 if (!argv[0]->isObject())
408 return NXSL_ERR_NOT_OBJECT;
409
410 NXSL_Object *object = argv[0]->getValueAsObject();
411 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
412 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
99030539
Z
413 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
414 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
415 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
d679defa
VK
416 return NXSL_ERR_BAD_CLASS;
417
418 NetObj *netobj = (NetObj *)object->getData();
419 *ppResult = new NXSL_Value(netobj->getChildrenForNXSL());
420 return 0;
421}
422
4dd963e9
VK
423/**
424 * Get node's interfaces
425 * First argument: node object
426 * Returns array of interface objects
427 */
6b29839d 428static int F_GetNodeInterfaces(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
6adc4a1a
VK
429{
430 if (!argv[0]->isObject())
431 return NXSL_ERR_NOT_OBJECT;
432
433 NXSL_Object *object = argv[0]->getValueAsObject();
434 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
435 return NXSL_ERR_BAD_CLASS;
436
437 Node *node = (Node *)object->getData();
438 *ppResult = new NXSL_Value(node->getInterfacesForNXSL());
439 return 0;
440}
441
4dd963e9
VK
442/**
443 * Get event's named parameter
444 * First argument: event object
445 * Second argument: parameter's name
446 * Returns parameter's value or null
447 */
6b29839d 448static int F_GetEventParameter(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
ed806a1a
VK
449{
450 if (!argv[0]->isObject())
451 return NXSL_ERR_NOT_OBJECT;
452
453 NXSL_Object *object = argv[0]->getValueAsObject();
454 if (_tcscmp(object->getClass()->getName(), g_nxslEventClass.getName()))
455 return NXSL_ERR_BAD_CLASS;
456
457 if (!argv[1]->isString())
458 return NXSL_ERR_NOT_STRING;
459
460 Event *e = (Event *)object->getData();
461 const TCHAR *value = e->getNamedParameter(argv[1]->getValueAsCString());
462 *ppResult = (value != NULL) ? new NXSL_Value(value) : new NXSL_Value;
463 return 0;
464}
465
4dd963e9
VK
466/**
467 * Set event's named parameter
468 * First argument: event object
469 * Second argument: parameter's name
470 * Third argument: new value
471 */
6b29839d 472static int F_SetEventParameter(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
24dc5346
VK
473{
474 if (!argv[0]->isObject())
475 return NXSL_ERR_NOT_OBJECT;
476
477 NXSL_Object *object = argv[0]->getValueAsObject();
478 if (_tcscmp(object->getClass()->getName(), g_nxslEventClass.getName()))
479 return NXSL_ERR_BAD_CLASS;
480
481 if (!argv[1]->isString() || !argv[2]->isString())
482 return NXSL_ERR_NOT_STRING;
483
484 Event *e = (Event *)object->getData();
485 e->setNamedParameter(argv[1]->getValueAsCString(), argv[2]->getValueAsCString());
486 *ppResult = new NXSL_Value;
487 return 0;
488}
489
4dd963e9
VK
490/**
491 * Post event
492 * Syntax:
493 * PostEvent(node, event, tag, ...)
494 * where:
495 * node - node object to send event on behalf of
496 * event - event code
497 * tag - user tag (optional)
498 * ... - optional parameters, will be passed as %1, %2, etc.
499 */
6b29839d 500static int F_PostEvent(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
8ebb2e89
VK
501{
502 if (argc < 2)
503 return NXSL_ERR_INVALID_ARGUMENT_COUNT;
504
505 // Validate first argument
506 if (!argv[0]->isObject())
507 return NXSL_ERR_NOT_OBJECT;
aa28fcea 508
8ebb2e89
VK
509 NXSL_Object *object = argv[0]->getValueAsObject();
510 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
511 return NXSL_ERR_BAD_CLASS;
512
513 Node *node = (Node *)object->getData();
514
a6cc48cc
VK
515 // Event code
516 if (!argv[1]->isString())
517 return NXSL_ERR_NOT_STRING;
8ebb2e89 518
967893bb 519 UINT32 eventCode = 0;
a6cc48cc
VK
520 if (argv[1]->isInteger())
521 {
522 eventCode = argv[1]->getValueAsUInt32();
523 }
524 else
8ebb2e89 525 {
a6cc48cc 526 eventCode = EventCodeFromName(argv[1]->getValueAsCString(), 0);
8ebb2e89
VK
527 }
528
a6cc48cc
VK
529 BOOL success;
530 if (eventCode > 0)
531 {
532 // User tag
533 const TCHAR *userTag = NULL;
534 if ((argc > 2) && !argv[2]->isNull())
535 {
536 if (!argv[2]->isString())
537 return NXSL_ERR_NOT_STRING;
538 userTag = argv[2]->getValueAsCString();
539 }
540
541 // Post event
542 char format[] = "ssssssssssssssssssssssssssssssss";
543 const TCHAR *plist[32];
544 int eargc = 0;
545 for(int i = 3; (i < argc) && (eargc < 32); i++)
546 plist[eargc++] = argv[i]->getValueAsCString();
547 format[eargc] = 0;
c42b4551 548 success = PostEventWithTag(eventCode, node->getId(), userTag, format,
a6cc48cc
VK
549 plist[0], plist[1], plist[2], plist[3],
550 plist[4], plist[5], plist[6], plist[7],
551 plist[8], plist[9], plist[10], plist[11],
552 plist[12], plist[13], plist[14], plist[15],
553 plist[16], plist[17], plist[18], plist[19],
554 plist[20], plist[21], plist[22], plist[23],
555 plist[24], plist[25], plist[26], plist[27],
556 plist[28], plist[29], plist[30], plist[31]);
557 }
558 else
559 {
560 success = FALSE;
561 }
8ebb2e89
VK
562
563 *ppResult = new NXSL_Value((LONG)success);
564 return 0;
565}
566
ea12c2aa
VK
567/**
568 * Create node object
569 * Syntax:
570 * CreateNode(parent, name, primaryHostName)
571 * where:
572 * parent - parent object
573 * name - name for new node
574 * primaryHostName - primary host name for new node
575 * Return value:
576 * new node object or null on failure
577 */
6b29839d 578static int F_CreateNode(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
ea12c2aa
VK
579{
580 if (!argv[0]->isObject())
581 return NXSL_ERR_NOT_OBJECT;
582
583 NXSL_Object *obj = argv[0]->getValueAsObject();
584 if (_tcscmp(obj->getClass()->getName(), g_nxslNetObjClass.getName()))
585 return NXSL_ERR_BAD_CLASS;
586
587 NetObj *parent = (NetObj*)obj->getData();
c42b4551 588 if (parent->getObjectClass() != OBJECT_CONTAINER && parent->getObjectClass() != OBJECT_SERVICEROOT)
ea12c2aa
VK
589 return NXSL_ERR_BAD_CLASS;
590
591 if (!argv[1]->isString() || !argv[2]->isString())
592 return NXSL_ERR_NOT_STRING;
593
594 const TCHAR *pname = argv[2]->getValueAsCString();
595 if (*pname == 0)
596 pname = argv[1]->getValueAsCString();
de4c3060 597 Node *node = PollNewNode(InetAddress::resolveHostName(pname), 0, 0, 0, argv[1]->getValueAsCString(), 0, 0, 0, 0, NULL, NULL, NULL, 0, true, false);
ea12c2aa
VK
598 if (node != NULL)
599 {
600 node->setPrimaryName(pname);
1f8be1f4
VK
601 parent->addChild(node);
602 node->addParent(parent);
ea12c2aa
VK
603 node->unhide();
604 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, node));
605 }
606 else
607 {
608 *ppResult = new NXSL_Value;
609 }
610 return 0;
611}
612
4dd963e9
VK
613/**
614 * Create container object
615 * Syntax:
616 * CreateContainer(parent, name)
617 * where:
618 * parent - parent object
619 * name - name for new container
620 * Return value:
621 * new container object
622 */
6b29839d 623static int F_CreateContainer(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
3bbc7435 624{
3bbc7435
AK
625 if (!argv[0]->isObject())
626 return NXSL_ERR_NOT_OBJECT;
627
628 NXSL_Object *obj = argv[0]->getValueAsObject();
629 if (_tcscmp(obj->getClass()->getName(), g_nxslNetObjClass.getName()))
630 return NXSL_ERR_BAD_CLASS;
631
632 NetObj *parent = (NetObj*)obj->getData();
c42b4551 633 if (parent->getObjectClass() != OBJECT_CONTAINER && parent->getObjectClass() != OBJECT_SERVICEROOT)
3bbc7435
AK
634 return NXSL_ERR_BAD_CLASS;
635
636 if (!argv[1]->isString())
637 return NXSL_ERR_NOT_STRING;
638
639 const TCHAR *name = argv[1]->getValueAsCString();
640
641 Container *container = new Container(name, 0);
e7450f3b 642 NetObjInsert(container, true, false);
1f8be1f4
VK
643 parent->addChild(container);
644 container->addParent(parent);
b648d82a 645 container->unhide();
3bbc7435
AK
646
647 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslNetObjClass, container));
648
649 return 0;
650}
651
4dd963e9 652/**
929bfb6b 653 * Delete object
4dd963e9 654 * Syntax:
929bfb6b 655 * DeleteObject(object)
4dd963e9 656 * where:
929bfb6b 657 * object - object to remove, must be of class NetObj, Interface, or Node
4dd963e9
VK
658 * Return value:
659 * null
660 */
6b29839d 661static int F_DeleteObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
3bbc7435 662{
3bbc7435
AK
663 if (!argv[0]->isObject())
664 return NXSL_ERR_NOT_OBJECT;
665
666 NXSL_Object *obj = argv[0]->getValueAsObject();
929bfb6b
VK
667 if (_tcscmp(obj->getClass()->getName(), g_nxslNetObjClass.getName()) &&
668 _tcscmp(obj->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
99030539
Z
669 _tcscmp(obj->getClass()->getName(), g_nxslNodeClass.getName()) &&
670 _tcscmp(obj->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
671 _tcscmp(obj->getClass()->getName(), g_nxslClusterClass.getName()))
3bbc7435
AK
672 return NXSL_ERR_BAD_CLASS;
673
06a8857b 674 NetObj *netobj = (NetObj*)obj->getData();
06a8857b 675 netobj->deleteObject();
3bbc7435 676
b648d82a 677 *ppResult = new NXSL_Value;
3bbc7435
AK
678 return 0;
679}
680
4dd963e9
VK
681/**
682 * Bind object to container
683 * Syntax:
684 * BindObject(parent, child)
685 * where:
686 * parent - container object
687 * child - either node or container or subnet to be bound to parent
688 * Return value:
689 * null
690 */
6b29839d 691static int F_BindObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
3bbc7435 692{
3bbc7435
AK
693 if (!argv[0]->isObject() || !argv[1]->isObject())
694 return NXSL_ERR_NOT_OBJECT;
695
696 NXSL_Object *obj = argv[0]->getValueAsObject();
697 if (_tcscmp(obj->getClass()->getName(), g_nxslNetObjClass.getName()))
698 return NXSL_ERR_BAD_CLASS;
699
06a8857b 700 NetObj *netobj = (NetObj*)obj->getData();
c42b4551 701 if (netobj->getObjectClass() != OBJECT_CONTAINER)
3bbc7435
AK
702 return NXSL_ERR_BAD_CLASS;
703
704 NXSL_Object *obj2 = argv[1]->getValueAsObject();
aa28fcea 705 if (_tcscmp(obj2->getClass()->getName(), g_nxslNetObjClass.getName()) &&
3bbc7435
AK
706 _tcscmp(obj2->getClass()->getName(), g_nxslNodeClass.getName()))
707 return NXSL_ERR_BAD_CLASS;
708
709 NetObj *child = (NetObj*)obj2->getData();
c42b4551 710 if (child->getObjectClass() != OBJECT_CONTAINER && child->getObjectClass() != OBJECT_SUBNET && child->getObjectClass() != OBJECT_NODE)
3bbc7435
AK
711 return NXSL_ERR_BAD_CLASS;
712
c42b4551 713 if (child->isChild(netobj->getId())) // prevent loops
06a8857b
AK
714 return NXSL_ERR_INVALID_OBJECT_OPERATION;
715
1f8be1f4
VK
716 netobj->addChild(child);
717 child->addParent(netobj);
a32a63c8
AK
718 netobj->calculateCompoundStatus();
719
b648d82a 720 *ppResult = new NXSL_Value;
3bbc7435
AK
721
722 return 0;
723}
724
4dd963e9
VK
725/**
726 * Remove (unbind) object from container
727 * Syntax:
728 * UnbindObject(parent, child)
729 * where:
730 * parent - container object
731 * child - either node or container or subnet to be removed from container
732 * Return value:
733 * null
734 */
6b29839d 735static int F_UnbindObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
3bbc7435 736{
3bbc7435
AK
737 if (!argv[0]->isObject() || !argv[1]->isObject())
738 return NXSL_ERR_NOT_OBJECT;
739
740 NXSL_Object *obj = argv[0]->getValueAsObject();
741 if (_tcscmp(obj->getClass()->getName(), g_nxslNetObjClass.getName()))
742 return NXSL_ERR_BAD_CLASS;
743
06a8857b 744 NetObj *netobj = (NetObj*)obj->getData();
c42b4551 745 if (netobj->getObjectClass() != OBJECT_CONTAINER)
3bbc7435
AK
746 return NXSL_ERR_BAD_CLASS;
747
748 NXSL_Object *obj2 = argv[1]->getValueAsObject();
aa28fcea 749 if (_tcscmp(obj2->getClass()->getName(), g_nxslNetObjClass.getName()) &&
3bbc7435
AK
750 _tcscmp(obj2->getClass()->getName(), g_nxslNodeClass.getName()))
751 return NXSL_ERR_BAD_CLASS;
752
753 NetObj *child = (NetObj*)obj2->getData();
c42b4551 754 if (child->getObjectClass() != OBJECT_CONTAINER && child->getObjectClass() != OBJECT_SUBNET && child->getObjectClass() != OBJECT_NODE)
3bbc7435
AK
755 return NXSL_ERR_BAD_CLASS;
756
1f8be1f4
VK
757 netobj->deleteChild(child);
758 child->deleteParent(netobj);
3bbc7435 759
b648d82a
VK
760 *ppResult = new NXSL_Value;
761
3bbc7435
AK
762 return 0;
763}
8ebb2e89 764
4dd963e9
VK
765/**
766 * Rename object
767 * Syntax:
768 * RenameObject(object, name)
769 * where:
770 * object - NetXMS object (Node, Interface, or NetObj)
771 * name - new name for object
772 * Return value:
773 * null
774 */
6b29839d 775static int F_RenameObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
2773ef30
VK
776{
777 if (!argv[0]->isObject())
778 return NXSL_ERR_NOT_OBJECT;
779
780 if (!argv[1]->isString())
781 return NXSL_ERR_NOT_STRING;
782
783 NXSL_Object *object = argv[0]->getValueAsObject();
aa28fcea 784 if (_tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
2773ef30 785 _tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
99030539
Z
786 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
787 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
788 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
2773ef30
VK
789 return NXSL_ERR_BAD_CLASS;
790
791 ((NetObj *)object->getData())->setName(argv[1]->getValueAsCString());
792
793 *ppResult = new NXSL_Value;
8f99849c
VK
794 return 0;
795}
796
797/**
798 * Manage object (set to managed state)
799 * Syntax:
800 * ManageObject(object)
801 * where:
802 * object - NetXMS object (Node, Interface, or NetObj)
803 * Return value:
804 * null
805 */
6b29839d 806static int F_ManageObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
8f99849c
VK
807{
808 if (!argv[0]->isObject())
809 return NXSL_ERR_NOT_OBJECT;
810
811 NXSL_Object *object = argv[0]->getValueAsObject();
aa28fcea 812 if (_tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
8f99849c 813 _tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
99030539
Z
814 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
815 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
816 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
8f99849c
VK
817 return NXSL_ERR_BAD_CLASS;
818
819 ((NetObj *)object->getData())->setMgmtStatus(TRUE);
2773ef30 820
8f99849c
VK
821 *ppResult = new NXSL_Value;
822 return 0;
823}
824
825/**
826 * Unmanage object (set to unmanaged state)
827 * Syntax:
828 * UnmanageObject(object)
829 * where:
830 * object - NetXMS object (Node, Interface, or NetObj)
831 * Return value:
832 * null
833 */
6b29839d 834static int F_UnmanageObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
8f99849c
VK
835{
836 if (!argv[0]->isObject())
837 return NXSL_ERR_NOT_OBJECT;
838
839 NXSL_Object *object = argv[0]->getValueAsObject();
aa28fcea 840 if (_tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
8f99849c 841 _tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
99030539
Z
842 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
843 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
844 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
8f99849c
VK
845 return NXSL_ERR_BAD_CLASS;
846
847 ((NetObj *)object->getData())->setMgmtStatus(FALSE);
848
849 *ppResult = new NXSL_Value;
2773ef30
VK
850 return 0;
851}
852
dea2a804
Z
853/**
854 * EnterMaintenance object (set to unmanaged state)
855 * Syntax:
856 * EnterMaintenance(object)
857 * where:
858 * object - NetXMS object (Node, Interface, or NetObj)
859 * Return value:
860 * null
861 */
862static int F_EnterMaintenance(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
863{
864 if (!argv[0]->isObject())
865 return NXSL_ERR_NOT_OBJECT;
866
867 NXSL_Object *object = argv[0]->getValueAsObject();
868 if (_tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
869 _tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
99030539
Z
870 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
871 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
872 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
dea2a804
Z
873 return NXSL_ERR_BAD_CLASS;
874
875 ((NetObj *)object->getData())->enterMaintenanceMode();
876
877 *ppResult = new NXSL_Value;
878 return 0;
879}
880
881/**
882 * LeaveMaintenance object (set to unmanaged state)
883 * Syntax:
884 * LeaveMaintenance(object)
885 * where:
886 * object - NetXMS object (Node, Interface, or NetObj)
887 * Return value:
888 * null
889 */
890static int F_LeaveMaintenance(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
891{
892 if (!argv[0]->isObject())
893 return NXSL_ERR_NOT_OBJECT;
894
895 NXSL_Object *object = argv[0]->getValueAsObject();
896 if (_tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
897 _tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
99030539
Z
898 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
899 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
900 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
dea2a804
Z
901 return NXSL_ERR_BAD_CLASS;
902
903 ((NetObj *)object->getData())->leaveMaintenanceMode();
904
905 *ppResult = new NXSL_Value;
906 return 0;
907}
908
909
707b18df
VK
910/**
911 * Set interface expected state
912 * Syntax:
913 * SetInterfaceExpectedState(interface, state)
914 * where:
915 * interface - Interface object
916 * state - state ID or name. Possible values: 0 "UP", 1 "DOWN", 2 "IGNORE"
917 * Return value:
918 * null
919 */
6b29839d 920static int F_SetInterfaceExpectedState(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
707b18df
VK
921{
922 if (!argv[0]->isObject())
923 return NXSL_ERR_NOT_OBJECT;
924
925 NXSL_Object *object = argv[0]->getValueAsObject();
926 if (_tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()))
927 return NXSL_ERR_BAD_CLASS;
928
929 int state;
930 if (argv[1]->isInteger())
931 {
932 state = argv[1]->getValueAsInt32();
933 }
934 else if (argv[1]->isString())
935 {
993ec488 936 static const TCHAR *stateNames[] = { _T("UP"), _T("DOWN"), _T("IGNORE"), NULL };
707b18df
VK
937 const TCHAR *name = argv[1]->getValueAsCString();
938 for(state = 0; stateNames[state] != NULL; state++)
939 if (!_tcsicmp(stateNames[state], name))
940 break;
941 }
942 else
943 {
944 return NXSL_ERR_NOT_STRING;
945 }
946
947 if ((state >= 0) && (state <= 2))
948 ((Interface *)object->getData())->setExpectedState(state);
949
950 *ppResult = new NXSL_Value;
951 return 0;
952}
953
4dd963e9
VK
954/**
955 * Create new SNMP transport object
956 * Syntax:
957 * CreateSNMPTransport(node)
958 * where:
959 * node - node to create SNMP transport for
960 * Return value:
961 * new SNMP_Transport object
962 */
6b29839d 963static int F_CreateSNMPTransport(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
e7c4e97b
AK
964{
965 if (!argv[0]->isObject())
966 return NXSL_ERR_NOT_OBJECT;
967
968 NXSL_Object *obj = argv[0]->getValueAsObject();
969 if (_tcscmp(obj->getClass()->getName(), g_nxslNodeClass.getName()))
970 return NXSL_ERR_BAD_CLASS;
971
972 Node *node = (Node*)obj->getData();
973 if (node != NULL)
974 {
61b359bc
VK
975 SNMP_Transport *t = node->createSnmpTransport();
976 *ppResult = (t != NULL) ? new NXSL_Value(new NXSL_Object(&g_nxslSnmpTransportClass, t)) : new NXSL_Value;
e7c4e97b
AK
977 }
978 else
979 {
980 *ppResult = new NXSL_Value;
981 }
982
983 return 0;
984}
985
4dd963e9
VK
986/**
987 * Do SNMP GET for the given object id
988 * Syntax:
989 * SNMPGet(transport, oid)
990 * where:
991 * transport - NXSL transport object
992 * oid - SNMP object id
993 * Return value:
994 * new SNMP_VarBind object
995 */
6b29839d 996static int F_SNMPGet(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
e7c4e97b 997{
967893bb
VK
998 UINT32 len;
999 static UINT32 requestId = 1;
e0471fad 1000 UINT32 varName[MAX_OID_LEN], result = SNMP_ERR_SUCCESS;
e7c4e97b
AK
1001
1002 if (!argv[0]->isObject())
1003 return NXSL_ERR_NOT_OBJECT;
1004 if (!argv[1]->isString())
1005 return NXSL_ERR_NOT_STRING;
1006
1007 NXSL_Object *obj = argv[0]->getValueAsObject();
1008 if (_tcscmp(obj->getClass()->getName(), g_nxslSnmpTransportClass.getName()))
1009 return NXSL_ERR_BAD_CLASS;
1010
1011 SNMP_Transport *trans = (SNMP_Transport*)obj->getData();
1012
f74002ab 1013 // Create PDU and send request
e0471fad 1014 size_t nameLen = SNMPParseOID(argv[1]->getValueAsString(&len), varName, MAX_OID_LEN);
f74002ab
AK
1015 if (nameLen == 0)
1016 return NXSL_ERR_BAD_CONDITION;
1017
486942d7 1018 SNMP_PDU *pdu = new SNMP_PDU(SNMP_GET_REQUEST, requestId++, trans->getSnmpVersion());
f74002ab 1019 pdu->bindVariable(new SNMP_Variable(varName, nameLen));
f74002ab 1020
486942d7 1021 SNMP_PDU *rspPDU;
296ae03d 1022 result = trans->doRequest(pdu, &rspPDU, SnmpGetDefaultTimeout(), 3);
486942d7 1023 if (result == SNMP_ERR_SUCCESS)
f74002ab 1024 {
486942d7
VK
1025 if ((rspPDU->getNumVariables() > 0) && (rspPDU->getErrorCode() == SNMP_PDU_ERR_SUCCESS))
1026 {
1027 SNMP_Variable *pVar = rspPDU->getVariable(0);
1028 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslSnmpVarBindClass, pVar));
f3d71512 1029 rspPDU->unlinkVariables();
486942d7
VK
1030 }
1031 else
1032 {
1033 *ppResult = new NXSL_Value;
1034 }
1035 delete rspPDU;
1036 }
e7c4e97b
AK
1037 else
1038 {
1039 *ppResult = new NXSL_Value;
1040 }
e6b6ae46 1041 delete pdu;
e7c4e97b
AK
1042 return 0;
1043}
1044
4dd963e9
VK
1045/**
1046 * Do SNMP GET for the given object id
1047 * Syntax:
1048 * SNMPGetValue(transport, oid)
1049 * where:
1050 * transport - NXSL transport object
1051 * oid - SNMP object id
1052 * Return value:
1053 * value for the given oid
1054 */
6b29839d 1055static int F_SNMPGetValue(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
e7c4e97b
AK
1056{
1057 TCHAR buffer[4096];
967893bb 1058 UINT32 len;
e7c4e97b
AK
1059
1060 if (!argv[0]->isObject())
1061 return NXSL_ERR_NOT_OBJECT;
1062 if (!argv[1]->isString())
1063 return NXSL_ERR_NOT_STRING;
1064
1065 NXSL_Object *obj = argv[0]->getValueAsObject();
1066 if (_tcscmp(obj->getClass()->getName(), g_nxslSnmpTransportClass.getName()))
1067 return NXSL_ERR_BAD_CLASS;
1068
1069 SNMP_Transport *trans = (SNMP_Transport*)obj->getData();
1070
0ec8d4c1 1071 if (SnmpGetEx(trans, argv[1]->getValueAsString(&len), NULL, 0, buffer, sizeof(buffer), SG_STRING_RESULT, NULL) == SNMP_ERR_SUCCESS)
e7c4e97b
AK
1072 {
1073 *ppResult = new NXSL_Value(buffer);
1074 }
1075 else
1076 {
1077 *ppResult = new NXSL_Value;
1078 }
1079
1080 return 0;
1081}
1082
4dd963e9
VK
1083/**
1084 * Do SNMP SET for the given object id
1085 * Syntax:
1086 * SNMPSet(transport, oid, value, [data_type])
1087 * where:
1088 * transport - NXSL transport object
1089 * oid - SNMP object id
1090 * value - value to set
1091 * data_type (optional)
1092 * Return value:
1093 * value for the given oid
1094 */
6b29839d 1095static int F_SNMPSet(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
e7c4e97b 1096{
486942d7 1097 SNMP_PDU *request = NULL, *response;
967893bb 1098 UINT32 len;
72d6a6e1 1099 LONG ret = FALSE;
f74002ab
AK
1100
1101 if (argc < 3 || argc > 4)
1102 return NXSL_ERR_INVALID_ARGUMENT_COUNT;
1103 if (!argv[0]->isObject())
1104 return NXSL_ERR_NOT_OBJECT;
1105 if (!argv[1]->isString() || !argv[2]->isString() || (argc == 4 && !argv[3]->isString()))
1106 return NXSL_ERR_NOT_STRING;
1107
1108 NXSL_Object *obj = argv[0]->getValueAsObject();
1109 if (_tcscmp(obj->getClass()->getName(), g_nxslSnmpTransportClass.getName()))
1110 return NXSL_ERR_BAD_CLASS;
1111
1112 SNMP_Transport *trans = (SNMP_Transport*)obj->getData();
1113
1114 // Create request
1115 request = new SNMP_PDU(SNMP_SET_REQUEST, getpid(), trans->getSnmpVersion());
1116
1117 if (SNMPIsCorrectOID(argv[1]->getValueAsString(&len)))
1118 {
1119 SNMP_Variable *var = new SNMP_Variable(argv[1]->getValueAsString(&len));
1120 if (argc == 3)
1121 {
e0471fad 1122 var->setValueFromString(ASN_OCTET_STRING, argv[2]->getValueAsString(&len));
f74002ab
AK
1123 }
1124 else
1125 {
967893bb 1126 UINT32 dataType = SNMPResolveDataType(argv[3]->getValueAsString(&len));
f74002ab
AK
1127 if (dataType == ASN_NULL)
1128 {
aa28fcea 1129 DbgPrintf(6, _T("SNMPSet: failed to resolve data type '%s', assume string"),
f74002ab
AK
1130 argv[3]->getValueAsString(&len));
1131 dataType = ASN_OCTET_STRING;
1132 }
e0471fad 1133 var->setValueFromString(dataType, argv[2]->getValueAsString(&len));
f74002ab
AK
1134 }
1135 request->bindVariable(var);
1136 }
1137 else
1138 {
72d6a6e1 1139 DbgPrintf(6, _T("SNMPSet: Invalid OID: %s"), argv[1]->getValueAsString(&len));
f74002ab
AK
1140 goto finish;
1141 }
1142
1143 // Send request and process response
967893bb 1144 UINT32 snmpResult;
296ae03d 1145 if ((snmpResult = trans->doRequest(request, &response, SnmpGetDefaultTimeout(), 3)) == SNMP_ERR_SUCCESS)
f74002ab
AK
1146 {
1147 if (response->getErrorCode() != 0)
1148 {
72d6a6e1 1149 DbgPrintf(6, _T("SNMPSet: operation failed (error code %d)"), response->getErrorCode());
f74002ab
AK
1150 goto finish;
1151 }
72d6a6e1
AK
1152 else
1153 {
1154 DbgPrintf(6, _T("SNMPSet: success"));
1155 ret = TRUE;
1156 }
f74002ab
AK
1157 delete response;
1158 }
1159 else
1160 {
72d6a6e1 1161 DbgPrintf(6, _T("SNMPSet: %s"), SNMPGetErrorText(snmpResult));
f74002ab
AK
1162 }
1163
1164finish:
486942d7 1165 delete request;
72d6a6e1 1166 *ppResult = new NXSL_Value(ret);
e7c4e97b
AK
1167 return 0;
1168}
1169
9ceab287
VK
1170/**
1171 * SNMP walk callback
1172 */
1173static UINT32 WalkCallback(SNMP_Variable *var, SNMP_Transport *transport, void *userArg)
1174{
1175 ((NXSL_Array *)userArg)->add(new NXSL_Value(new NXSL_Object(&g_nxslSnmpVarBindClass, new SNMP_Variable(var))));
1176 return SNMP_ERR_SUCCESS;
1177}
1178
fdbee7f8
VK
1179/**
1180 * Do SNMP walk starting from the given oid
1181 * Syntax:
1182 * SNMPWalk(transport, oid)
1183 * where:
1184 * transport - NXSL transport object
1185 * oid - SNMP object id
1186 * Return value:
1187 * an array of VarBind objects
1188 */
6b29839d 1189static int F_SNMPWalk(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
e7c4e97b 1190{
f74002ab
AK
1191 if (!argv[0]->isObject())
1192 return NXSL_ERR_NOT_OBJECT;
1193 if (!argv[1]->isString())
1194 return NXSL_ERR_NOT_STRING;
1195
f74002ab
AK
1196 NXSL_Object *obj = argv[0]->getValueAsObject();
1197 if (_tcscmp(obj->getClass()->getName(), g_nxslSnmpTransportClass.getName()))
1198 return NXSL_ERR_BAD_CLASS;
1199
9ceab287
VK
1200 NXSL_Array *varList = new NXSL_Array;
1201 SNMP_Transport *transport = (SNMP_Transport *)obj->getData();
1202 UINT32 result = SnmpWalk(transport, argv[1]->getValueAsCString(), WalkCallback, varList);
1203 if (result == SNMP_ERR_SUCCESS)
f74002ab 1204 {
9ceab287 1205 *ppResult = new NXSL_Value(varList);
f74002ab 1206 }
f74002ab 1207 else
9ceab287
VK
1208 {
1209 *ppResult = new NXSL_Value;
1210 delete varList;
1211 }
e7c4e97b
AK
1212 return 0;
1213}
58190c34 1214
1e84fc1d
VK
1215/**
1216 * Execute agent action
1217 * Syntax:
1218 * AgentExecuteAction(object, name, ...)
1219 * where:
1220 * object - NetXMS node object
1221 * name - name of the parameter
1222 * Return value:
1223 * paramater's value on success and null on failure
1224 */
1225static int F_AgentExecuteAction(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
1226{
1227 if (argc < 2)
1228 return NXSL_ERR_INVALID_ARGUMENT_COUNT;
1229
1230 if (!argv[0]->isObject())
1231 return NXSL_ERR_NOT_OBJECT;
1232
1233 for(int i = 1; i < argc; i++)
1234 if (!argv[i]->isString())
1235 return NXSL_ERR_NOT_STRING;
1236
1237 NXSL_Object *object = argv[0]->getValueAsObject();
1238 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
1239 return NXSL_ERR_BAD_CLASS;
1240
1241 Node *node = (Node *)object->getData();
1242 AgentConnection *conn = node->createAgentConnection();
1243 if (conn != NULL)
1244 {
1245 const TCHAR *args[128];
1246 for(int i = 2; (i < argc) && (i < 128); i++)
1247 args[i - 2] = argv[i]->getValueAsCString();
1248 UINT32 rcc = conn->execAction(argv[1]->getValueAsCString(), argc - 2, args, false, NULL, NULL);
1249 *ppResult = new NXSL_Value((rcc == ERR_SUCCESS) ? 1 : 0);
1250 conn->decRefCount();
1251 nxlog_debug(5, _T("NXSL: F_AgentExecuteAction: action %s on node %s [%d]: RCC=%d"), argv[1]->getValueAsCString(), node->getName(), node->getId(), rcc);
1252 }
1253 else
1254 {
1255 *ppResult = new NXSL_Value(0);
1256 }
1257 return 0;
1258}
1259
8f99849c
VK
1260/**
1261 * Read parameter's value from agent
1262 * Syntax:
1263 * AgentReadParameter(object, name)
1264 * where:
1265 * object - NetXMS node object
1266 * name - name of the parameter
1267 * Return value:
1268 * paramater's value on success and null on failure
1269 */
6b29839d 1270static int F_AgentReadParameter(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
8f99849c
VK
1271{
1272 if (!argv[0]->isObject())
1273 return NXSL_ERR_NOT_OBJECT;
1274
1275 if (!argv[1]->isString())
1276 return NXSL_ERR_NOT_STRING;
1277
1278 NXSL_Object *object = argv[0]->getValueAsObject();
1279 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
1280 return NXSL_ERR_BAD_CLASS;
1281
1282 TCHAR buffer[MAX_RESULT_LENGTH];
967893bb 1283 UINT32 rcc = ((Node *)object->getData())->getItemFromAgent(argv[1]->getValueAsCString(), MAX_RESULT_LENGTH, buffer);
8f99849c
VK
1284 if (rcc == DCE_SUCCESS)
1285 *ppResult = new NXSL_Value(buffer);
1286 else
1287 *ppResult = new NXSL_Value;
1288 return 0;
1289}
1290
bb9ba0c7
VK
1291/**
1292 * Read table value from agent
1293 * Syntax:
1294 * AgentReadTable(object, name)
1295 * where:
1296 * object - NetXMS node object
1297 * name - name of the table
1298 * Return value:
1299 * table value on success and null on failure
1300 */
6b29839d 1301static int F_AgentReadTable(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
bb9ba0c7
VK
1302{
1303 if (!argv[0]->isObject())
1304 return NXSL_ERR_NOT_OBJECT;
1305
1306 if (!argv[1]->isString())
1307 return NXSL_ERR_NOT_STRING;
1308
1309 NXSL_Object *object = argv[0]->getValueAsObject();
1310 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
1311 return NXSL_ERR_BAD_CLASS;
1312
1313 Table *table;
1314 UINT32 rcc = ((Node *)object->getData())->getTableFromAgent(argv[1]->getValueAsCString(), &table);
1315 if (rcc == DCE_SUCCESS)
1316 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslTableClass, table));
1317 else
1318 *ppResult = new NXSL_Value;
1319 return 0;
1320}
1321
067aa4ab
VK
1322/**
1323 * Read list from agent
1324 * Syntax:
1325 * AgentReadList(object, name)
1326 * where:
1327 * object - NetXMS node object
1328 * name - name of the list
1329 * Return value:
1330 * list values (as an array) on success and null on failure
1331 */
1332static int F_AgentReadList(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
1333{
1334 if (!argv[0]->isObject())
1335 return NXSL_ERR_NOT_OBJECT;
1336
1337 if (!argv[1]->isString())
1338 return NXSL_ERR_NOT_STRING;
1339
1340 NXSL_Object *object = argv[0]->getValueAsObject();
1341 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
1342 return NXSL_ERR_BAD_CLASS;
1343
1344 StringList *list;
1345 UINT32 rcc = ((Node *)object->getData())->getListFromAgent(argv[1]->getValueAsCString(), &list);
1346 if (rcc == DCE_SUCCESS)
1347 *ppResult = new NXSL_Value(new NXSL_Array(list));
1348 else
1349 *ppResult = new NXSL_Value;
1350 delete list;
1351 return 0;
1352}
1353
fdbee7f8
VK
1354/**
1355 * Get server's configuration variable
1356 * First argument is a variable name
1357 * Optional second argumet is default value
1358 * Returns variable's value if found, default value if not found, and null if not found and no default value given
1359 */
6b29839d 1360static int F_GetConfigurationVariable(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
3984a442
VK
1361{
1362 if ((argc == 0) || (argc > 2))
1363 return NXSL_ERR_INVALID_ARGUMENT_COUNT;
1364
1365 if (!argv[0]->isString())
1366 return NXSL_ERR_NOT_STRING;
1367
2589cc10 1368 TCHAR buffer[MAX_CONFIG_VALUE];
1369 if (ConfigReadStr(argv[0]->getValueAsCString(), buffer, MAX_CONFIG_VALUE, _T("")))
3984a442
VK
1370 {
1371 *ppResult = new NXSL_Value(buffer);
1372 }
1373 else
1374 {
1375 *ppResult = (argc == 2) ? new NXSL_Value(argv[1]) : new NXSL_Value;
1376 }
1377
1378 return 0;
1379}
1380
0de31ec3
VK
1381/**
1382 * Get country alpha code from numeric code
1383 */
1384static int F_CountryAlphaCode(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm)
1385{
1386 if (!argv[0]->isString())
1387 return NXSL_ERR_NOT_STRING;
1388
1389 const TCHAR *code = CountryAlphaCode(argv[0]->getValueAsCString());
1390 *result = (code != NULL) ? new NXSL_Value(code) : new NXSL_Value();
1391 return 0;
1392}
1393
1394/**
1395 * Get country name from code
1396 */
1397static int F_CountryName(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm)
1398{
1399 if (!argv[0]->isString())
1400 return NXSL_ERR_NOT_STRING;
1401
1402 const TCHAR *name = CountryName(argv[0]->getValueAsCString());
1403 *result = (name != NULL) ? new NXSL_Value(name) : new NXSL_Value();
1404 return 0;
1405}
1406
1407/**
1408 * Get currency alpha code from numeric code
1409 */
1410static int F_CurrencyAlphaCode(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm)
1411{
1412 if (!argv[0]->isString())
1413 return NXSL_ERR_NOT_STRING;
1414
1415 const TCHAR *code = CurrencyAlphaCode(argv[0]->getValueAsCString());
1416 *result = (code != NULL) ? new NXSL_Value(code) : new NXSL_Value();
1417 return 0;
1418}
1419
1420/**
1421 * Get currency exponent
1422 */
1423static int F_CurrencyExponent(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm)
1424{
1425 if (!argv[0]->isString())
1426 return NXSL_ERR_NOT_STRING;
1427
1428 *result = new NXSL_Value(CurrencyExponent(argv[0]->getValueAsCString()));
1429 return 0;
1430}
1431
1432/**
1433 * Get country name from code
1434 */
1435static int F_CurrencyName(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm)
1436{
1437 if (!argv[0]->isString())
1438 return NXSL_ERR_NOT_STRING;
1439
1440 const TCHAR *name = CurrencyName(argv[0]->getValueAsCString());
1441 *result = (name != NULL) ? new NXSL_Value(name) : new NXSL_Value();
1442 return 0;
1443}
1444
fdbee7f8
VK
1445/**
1446 * Additional server functions to use within all scripts
1447 */
5039dede
AK
1448static NXSL_ExtFunction m_nxslServerFunctions[] =
1449{
4dd963e9 1450 { _T("map"), F_map, -1 },
24a5d5ab 1451 { _T("mapList"), F_mapList, -1 },
1e84fc1d 1452 { _T("AgentExecuteAction"), F_AgentExecuteAction, -1 },
067aa4ab 1453 { _T("AgentReadList"), F_AgentReadList, 2 },
8f99849c 1454 { _T("AgentReadParameter"), F_AgentReadParameter, 2 },
bb9ba0c7 1455 { _T("AgentReadTable"), F_AgentReadTable, 2 },
06c104c6 1456 { _T("CreateSNMPTransport"), F_CreateSNMPTransport, 1 },
0de31ec3
VK
1457 { _T("CountryAlphaCode"), F_CountryAlphaCode, 1 },
1458 { _T("CountryName"), F_CountryName, 1 },
1459 { _T("CurrencyAlphaCode"), F_CurrencyAlphaCode, 1 },
1460 { _T("CurrencyExponent"), F_CurrencyExponent, 1 },
1461 { _T("CurrencyName"), F_CurrencyName, 1 },
aa28fcea 1462 { _T("DeleteCustomAttribute"), F_DeleteCustomAttribute, 2 },
0de31ec3 1463 { _T("EnterMaintenance"), F_EnterMaintenance, 1 },
3984a442 1464 { _T("GetConfigurationVariable"), F_GetConfigurationVariable, -1 },
35f836fe 1465 { _T("GetCustomAttribute"), F_GetCustomAttribute, 2 },
ed806a1a 1466 { _T("GetEventParameter"), F_GetEventParameter, 2 },
35f836fe 1467 { _T("GetInterfaceName"), F_GetInterfaceName, 2 },
09e834a1 1468 { _T("GetInterfaceObject"), F_GetInterfaceObject, 2 },
6adc4a1a 1469 { _T("GetNodeInterfaces"), F_GetNodeInterfaces, 1 },
35f836fe 1470 { _T("GetNodeParents"), F_GetNodeParents, 1 },
0ae82278 1471 { _T("GetNodeTemplates"), F_GetNodeTemplates, 1 },
d679defa 1472 { _T("GetObjectChildren"), F_GetObjectChildren, 1 },
06c104c6 1473 { _T("GetObjectParents"), F_GetObjectParents, 1 },
459f4057
VK
1474 { _T("FindAlarmById"), F_FindAlarmById, 1 },
1475 { _T("FindAlarmByKey"), F_FindAlarmByKey, 1 },
35f836fe 1476 { _T("FindNodeObject"), F_FindNodeObject, 2 },
58190c34 1477 { _T("FindObject"), F_FindObject, -1 },
0de31ec3 1478 { _T("LeaveMaintenance"), F_LeaveMaintenance, 1 },
8f99849c 1479 { _T("ManageObject"), F_ManageObject, 1 },
9daff89d 1480 { _T("PostEvent"), F_PostEvent, -1 },
8f99849c 1481 { _T("RenameObject"), F_RenameObject, 2 },
6adc4a1a
VK
1482 { _T("SetCustomAttribute"), F_SetCustomAttribute, 3 },
1483 { _T("SetEventParameter"), F_SetEventParameter, 3 },
707b18df 1484 { _T("SetInterfaceExpectedState"), F_SetInterfaceExpectedState, 2 },
e7c4e97b
AK
1485 { _T("SNMPGet"), F_SNMPGet, 2 },
1486 { _T("SNMPGetValue"), F_SNMPGetValue, 2 },
1487 { _T("SNMPSet"), F_SNMPSet, -1 /* 3 or 4 */ },
8f99849c 1488 { _T("SNMPWalk"), F_SNMPWalk, 2 },
0de31ec3 1489 { _T("UnmanageObject"), F_UnmanageObject, 1 }
5039dede
AK
1490};
1491
fdbee7f8 1492/**
8f99849c 1493 * Additional server functions to manage objects (disabled by default)
fdbee7f8 1494 */
3bbc7435
AK
1495static NXSL_ExtFunction m_nxslServerFunctionsForContainers[] =
1496{
06c104c6 1497 { _T("BindObject"), F_BindObject, 2 },
3bbc7435 1498 { _T("CreateContainer"), F_CreateContainer, 2 },
ea12c2aa 1499 { _T("CreateNode"), F_CreateNode, 3 },
929bfb6b 1500 { _T("DeleteObject"), F_DeleteObject, 1 },
8f99849c 1501 { _T("UnbindObject"), F_UnbindObject, 2 }
3bbc7435
AK
1502};
1503
529956a0 1504/*** NXSL_ServerEnv class implementation ***/
1505
2773ef30
VK
1506/**
1507 * Constructor for server default script environment
1508 */
fdbee7f8 1509NXSL_ServerEnv::NXSL_ServerEnv() : NXSL_Environment()
5039dede 1510{
2773ef30 1511 m_console = NULL;
bb5365ed
VK
1512 setLibrary(g_pScriptLibrary);
1513 registerFunctionSet(sizeof(m_nxslServerFunctions) / sizeof(NXSL_ExtFunction), m_nxslServerFunctions);
5039dede 1514 RegisterDCIFunctions(this);
bb5365ed 1515 registerFunctionSet(g_nxslNumSituationFunctions, g_nxslSituationFunctions);
c8076b19 1516 if (g_flags & AF_ENABLE_NXSL_CONTAINER_FUNCS)
3bbc7435 1517 registerFunctionSet(sizeof(m_nxslServerFunctionsForContainers) / sizeof(NXSL_ExtFunction), m_nxslServerFunctionsForContainers);
c0a48696 1518 // Pass event to modules
1519 CALL_ALL_MODULES(pfNXSLServerEnvConfig, (this));
bb5365ed
VK
1520}
1521
2773ef30
VK
1522/**
1523 * Script trace output
1524 */
bb5365ed
VK
1525void NXSL_ServerEnv::trace(int level, const TCHAR *text)
1526{
1527 if (level == 0)
1528 {
1529 nxlog_write(MSG_OTHER, EVENTLOG_INFORMATION_TYPE, "s", text);
1530 }
1531 else
1532 {
1533 DbgPrintf(level, _T("%s"), text);
1534 }
5039dede 1535}
2773ef30
VK
1536
1537/**
1538 * Print script output to console
1539 */
1540void NXSL_ServerEnv::print(NXSL_Value *value)
1541{
1542 if (m_console != NULL)
1543 {
1544 const TCHAR *text = value->getValueAsCString();
1545 ConsolePrintf(m_console, _T("%s"), CHECK_NULL(text));
1546 }
1547}
529956a0 1548
8f93930b
VK
1549/**
1550 * Additional VM configuration
1551 */
1552void NXSL_ServerEnv::configureVM(NXSL_VM *vm)
1553{
1554 CALL_ALL_MODULES(pfNXSLServerVMConfig, (vm));
1555}
1556
529956a0 1557/**
a3338f68 1558 * Constructor for environment intended for passing script's output to client
529956a0 1559 */
b368969c 1560NXSL_ClientSessionEnv::NXSL_ClientSessionEnv(ClientSession *session, NXCPMessage *response) : NXSL_ServerEnv()
529956a0 1561{
a3338f68
VK
1562 m_session = session;
1563 m_response = response;
529956a0 1564}
1565
1566/**
a3338f68 1567 * Send script output to user
529956a0 1568 */
a3338f68 1569void NXSL_ClientSessionEnv::print(NXSL_Value *value)
529956a0 1570{
a3338f68 1571 if (m_session != NULL && m_response != NULL)
529956a0 1572 {
9d850e8b 1573 const TCHAR *text = value->getValueAsCString();
b368969c 1574 m_response->setField(VID_MESSAGE, text);
a3338f68
VK
1575 m_session->sendMessage(m_response);
1576 }
1577}
1578
1579/**
1580 * Trace output
1581 */
1582void NXSL_ClientSessionEnv::trace(int level, const TCHAR *text)
1583{
1584 if (m_session != NULL && m_response != NULL)
1585 {
60c304b9
VK
1586 size_t len = _tcslen(text);
1587 TCHAR *t = (TCHAR *)malloc((len + 2) * sizeof(TCHAR));
1588 memcpy(t, text, len * sizeof(TCHAR));
818ebb6a
VK
1589 t[len] = _T('\n');
1590 t[len + 1] = 0;
b368969c 1591 m_response->setField(VID_MESSAGE, t);
a3338f68 1592 m_session->sendMessage(m_response);
60c304b9 1593 free(t);
529956a0 1594 }
a3338f68 1595 NXSL_ServerEnv::trace(level, text);
529956a0 1596}
d9f013df
VK
1597
1598/**
1599 * Call hook script
1600 */
1601NXSL_VM *FindHookScript(const TCHAR *hookName)
1602{
1603 TCHAR scriptName[MAX_PATH] = _T("Hook::");
1604 nx_strncpy(&scriptName[6], hookName, MAX_PATH - 6);
1605 NXSL_VM *vm = g_pScriptLibrary->createVM(scriptName, new NXSL_ServerEnv);
1606 if (vm == NULL)
1607 DbgPrintf(7, _T("FindHookScript: hook script \"%s\" not found"), scriptName);
1608 return vm;
1609}