added NXSL function AgentExecuteAction
[public/netxms.git] / src / server / core / nxslext.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 Raden Solutions
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
25 /**
26 * Externals
27 */
28 extern UINT32 g_nxslNumSituationFunctions;
29 extern NXSL_ExtFunction g_nxslSituationFunctions[];
30
31 void RegisterDCIFunctions(NXSL_Environment *pEnv);
32 int F_map(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
33 int F_mapList(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
34
35 int F_FindAlarmById(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
36 int F_FindAlarmByKey(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
37
38 /**
39 * Get node's custom attribute
40 * First argument is a node object, and second is an attribute name
41 */
42 static int F_GetCustomAttribute(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
43 {
44 NXSL_Object *object;
45 const TCHAR *value;
46
47 if (!argv[0]->isObject())
48 return NXSL_ERR_NOT_OBJECT;
49
50 if (!argv[1]->isString())
51 return NXSL_ERR_NOT_STRING;
52
53 object = argv[0]->getValueAsObject();
54 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
55 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
56 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
57 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
58 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
59 return NXSL_ERR_BAD_CLASS;
60
61 NetObj *netxmsObject = (NetObj *)object->getData();
62 value = netxmsObject->getCustomAttribute(argv[1]->getValueAsCString());
63 if (value != NULL)
64 {
65 *ppResult = new NXSL_Value(value);
66 }
67 else
68 {
69 *ppResult = new NXSL_Value; // Return NULL if attribute not found
70 }
71
72 return 0;
73 }
74
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 */
80 static int F_SetCustomAttribute(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
81 {
82 NXSL_Object *object;
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();
92 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
93 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
94 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
95 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
96 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
97 return NXSL_ERR_BAD_CLASS;
98
99 NetObj *netxmsObject = (NetObj *)object->getData();
100 value = netxmsObject->getCustomAttribute(argv[1]->getValueAsCString());
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
110 netxmsObject->setCustomAttribute(argv[1]->getValueAsCString(), argv[2]->getValueAsCString());
111
112 return 0;
113 }
114
115 /**
116 * Delete node's custom attribute
117 * First argument is a node object, second is an attribute name
118 */
119 static int F_DeleteCustomAttribute(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
120 {
121 NXSL_Object *object;
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()) &&
132 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
133 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
134 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
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
143 /**
144 * Get interface name by index
145 * Parameters: node object and interface index
146 */
147 static int F_GetInterfaceName(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
148 {
149 if (!argv[0]->isObject())
150 return NXSL_ERR_NOT_OBJECT;
151
152 if (!argv[1]->isInteger())
153 return NXSL_ERR_NOT_INTEGER;
154
155 NXSL_Object *object = argv[0]->getValueAsObject();
156 if (_tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()))
157 return NXSL_ERR_BAD_CLASS;
158
159 Node *node = (Node *)object->getData();
160 Interface *ifc = node->findInterfaceByIndex(argv[1]->getValueAsUInt32());
161 if (ifc != NULL)
162 {
163 *ppResult = new NXSL_Value(ifc->getName());
164 }
165 else
166 {
167 *ppResult = new NXSL_Value; // Return NULL if interface not found
168 }
169
170 return 0;
171 }
172
173 /**
174 * Get interface object by index
175 * Parameters: node object and interface index
176 */
177 static int F_GetInterfaceObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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();
190 Interface *ifc = node->findInterfaceByIndex(argv[1]->getValueAsUInt32());
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
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 */
209 static int F_FindNodeObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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());
231 if ((o != NULL) && (o->getObjectClass() == OBJECT_NODE))
232 node = (Node *)o;
233 }
234 else
235 {
236 node = (Node *)FindObjectByName(argv[1]->getValueAsCString(), OBJECT_NODE);
237 }
238
239 if (node != NULL)
240 {
241 if (g_flags & AF_CHECK_TRUSTED_NODES)
242 {
243 if ((currNode != NULL) && (node->isTrustedNode(currNode->getId())))
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;
251 DbgPrintf(4, _T("NXSL::FindNodeObject(%s [%d], '%s'): access denied for node %s [%d]"),
252 (currNode != NULL) ? currNode->getName() : _T("null"), (currNode != NULL) ? currNode->getId() : 0,
253 argv[1]->getValueAsCString(), node->getName(), node->getId());
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
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 */
276 static int F_FindObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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
286 if (argc == 2 && (!argv[1]->isNull() && !argv[1]->isObject()))
287 return NXSL_ERR_NOT_OBJECT;
288
289 if (argv[0]->isInteger())
290 {
291 object = FindObjectById(argv[0]->getValueAsUInt32());
292 }
293 else
294 {
295 object = FindObjectByName(argv[0]->getValueAsCString(), -1);
296 }
297
298 if (object != NULL)
299 {
300 if (g_flags & AF_CHECK_TRUSTED_NODES)
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 }
311 if ((currNode != NULL) && (object->isTrustedNode(currNode->getId())))
312 {
313 *ppResult = object->createNXSLObject();
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(),
321 (currNode != NULL) ? currNode->getName() : _T("null"), (currNode != NULL) ? currNode->getId() : 0,
322 object->getName(), object->getId());
323 }
324 }
325 else
326 {
327 *ppResult = object->createNXSLObject();;
328 }
329 }
330 else
331 {
332 // Object not found, return null
333 *ppResult = new NXSL_Value;
334 }
335
336 return 0;
337 }
338
339 /**
340 * Get node object's parents
341 * First argument: node object
342 * Returns array of accessible parent objects
343 */
344 static int F_GetNodeParents(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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
358 /**
359 * Get node object's templates
360 * First argument: node object
361 * Returns array of accessible template objects
362 */
363 static 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
377 /**
378 * Get object's parents
379 * First argument: NetXMS object (NetObj, Node, or Interface)
380 * Returns array of accessible parent objects
381 */
382 static int F_GetObjectParents(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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()) &&
390 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
391 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
392 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
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
400 /**
401 * Get object's children
402 * First argument: NetXMS object (NetObj, Node, or Interface)
403 * Returns array of accessible child objects
404 */
405 static int F_GetObjectChildren(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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()) &&
413 _tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
414 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
415 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
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
423 /**
424 * Get node's interfaces
425 * First argument: node object
426 * Returns array of interface objects
427 */
428 static int F_GetNodeInterfaces(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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
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 */
448 static int F_GetEventParameter(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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
466 /**
467 * Set event's named parameter
468 * First argument: event object
469 * Second argument: parameter's name
470 * Third argument: new value
471 */
472 static int F_SetEventParameter(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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
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 */
500 static int F_PostEvent(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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;
508
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
515 // Event code
516 if (!argv[1]->isString())
517 return NXSL_ERR_NOT_STRING;
518
519 UINT32 eventCode = 0;
520 if (argv[1]->isInteger())
521 {
522 eventCode = argv[1]->getValueAsUInt32();
523 }
524 else
525 {
526 eventCode = EventCodeFromName(argv[1]->getValueAsCString(), 0);
527 }
528
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;
548 success = PostEventWithTag(eventCode, node->getId(), userTag, format,
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 }
562
563 *ppResult = new NXSL_Value((LONG)success);
564 return 0;
565 }
566
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 */
578 static int F_CreateNode(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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();
588 if (parent->getObjectClass() != OBJECT_CONTAINER && parent->getObjectClass() != OBJECT_SERVICEROOT)
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();
597 Node *node = PollNewNode(InetAddress::resolveHostName(pname), 0, 0, 0, argv[1]->getValueAsCString(), 0, 0, 0, 0, NULL, NULL, NULL, 0, true, false);
598 if (node != NULL)
599 {
600 node->setPrimaryName(pname);
601 parent->addChild(node);
602 node->addParent(parent);
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
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 */
623 static int F_CreateContainer(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
624 {
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();
633 if (parent->getObjectClass() != OBJECT_CONTAINER && parent->getObjectClass() != OBJECT_SERVICEROOT)
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);
642 NetObjInsert(container, true, false);
643 parent->addChild(container);
644 container->addParent(parent);
645 container->unhide();
646
647 *ppResult = new NXSL_Value(new NXSL_Object(&g_nxslNetObjClass, container));
648
649 return 0;
650 }
651
652 /**
653 * Delete object
654 * Syntax:
655 * DeleteObject(object)
656 * where:
657 * object - object to remove, must be of class NetObj, Interface, or Node
658 * Return value:
659 * null
660 */
661 static int F_DeleteObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
662 {
663 if (!argv[0]->isObject())
664 return NXSL_ERR_NOT_OBJECT;
665
666 NXSL_Object *obj = argv[0]->getValueAsObject();
667 if (_tcscmp(obj->getClass()->getName(), g_nxslNetObjClass.getName()) &&
668 _tcscmp(obj->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
669 _tcscmp(obj->getClass()->getName(), g_nxslNodeClass.getName()) &&
670 _tcscmp(obj->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
671 _tcscmp(obj->getClass()->getName(), g_nxslClusterClass.getName()))
672 return NXSL_ERR_BAD_CLASS;
673
674 NetObj *netobj = (NetObj*)obj->getData();
675 netobj->deleteObject();
676
677 *ppResult = new NXSL_Value;
678 return 0;
679 }
680
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 */
691 static int F_BindObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
692 {
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
700 NetObj *netobj = (NetObj*)obj->getData();
701 if (netobj->getObjectClass() != OBJECT_CONTAINER)
702 return NXSL_ERR_BAD_CLASS;
703
704 NXSL_Object *obj2 = argv[1]->getValueAsObject();
705 if (_tcscmp(obj2->getClass()->getName(), g_nxslNetObjClass.getName()) &&
706 _tcscmp(obj2->getClass()->getName(), g_nxslNodeClass.getName()))
707 return NXSL_ERR_BAD_CLASS;
708
709 NetObj *child = (NetObj*)obj2->getData();
710 if (child->getObjectClass() != OBJECT_CONTAINER && child->getObjectClass() != OBJECT_SUBNET && child->getObjectClass() != OBJECT_NODE)
711 return NXSL_ERR_BAD_CLASS;
712
713 if (child->isChild(netobj->getId())) // prevent loops
714 return NXSL_ERR_INVALID_OBJECT_OPERATION;
715
716 netobj->addChild(child);
717 child->addParent(netobj);
718 netobj->calculateCompoundStatus();
719
720 *ppResult = new NXSL_Value;
721
722 return 0;
723 }
724
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 */
735 static int F_UnbindObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
736 {
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
744 NetObj *netobj = (NetObj*)obj->getData();
745 if (netobj->getObjectClass() != OBJECT_CONTAINER)
746 return NXSL_ERR_BAD_CLASS;
747
748 NXSL_Object *obj2 = argv[1]->getValueAsObject();
749 if (_tcscmp(obj2->getClass()->getName(), g_nxslNetObjClass.getName()) &&
750 _tcscmp(obj2->getClass()->getName(), g_nxslNodeClass.getName()))
751 return NXSL_ERR_BAD_CLASS;
752
753 NetObj *child = (NetObj*)obj2->getData();
754 if (child->getObjectClass() != OBJECT_CONTAINER && child->getObjectClass() != OBJECT_SUBNET && child->getObjectClass() != OBJECT_NODE)
755 return NXSL_ERR_BAD_CLASS;
756
757 netobj->deleteChild(child);
758 child->deleteParent(netobj);
759
760 *ppResult = new NXSL_Value;
761
762 return 0;
763 }
764
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 */
775 static int F_RenameObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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();
784 if (_tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
785 _tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
786 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
787 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
788 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
789 return NXSL_ERR_BAD_CLASS;
790
791 ((NetObj *)object->getData())->setName(argv[1]->getValueAsCString());
792
793 *ppResult = new NXSL_Value;
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 */
806 static int F_ManageObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
807 {
808 if (!argv[0]->isObject())
809 return NXSL_ERR_NOT_OBJECT;
810
811 NXSL_Object *object = argv[0]->getValueAsObject();
812 if (_tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
813 _tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
814 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
815 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
816 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
817 return NXSL_ERR_BAD_CLASS;
818
819 ((NetObj *)object->getData())->setMgmtStatus(TRUE);
820
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 */
834 static int F_UnmanageObject(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
835 {
836 if (!argv[0]->isObject())
837 return NXSL_ERR_NOT_OBJECT;
838
839 NXSL_Object *object = argv[0]->getValueAsObject();
840 if (_tcscmp(object->getClass()->getName(), g_nxslNetObjClass.getName()) &&
841 _tcscmp(object->getClass()->getName(), g_nxslNodeClass.getName()) &&
842 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
843 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
844 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
845 return NXSL_ERR_BAD_CLASS;
846
847 ((NetObj *)object->getData())->setMgmtStatus(FALSE);
848
849 *ppResult = new NXSL_Value;
850 return 0;
851 }
852
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 */
862 static 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()) &&
870 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
871 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
872 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
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 */
890 static 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()) &&
898 _tcscmp(object->getClass()->getName(), g_nxslInterfaceClass.getName()) &&
899 _tcscmp(object->getClass()->getName(), g_nxslMobileDeviceClass.getName()) &&
900 _tcscmp(object->getClass()->getName(), g_nxslClusterClass.getName()))
901 return NXSL_ERR_BAD_CLASS;
902
903 ((NetObj *)object->getData())->leaveMaintenanceMode();
904
905 *ppResult = new NXSL_Value;
906 return 0;
907 }
908
909
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 */
920 static int F_SetInterfaceExpectedState(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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 {
936 static const TCHAR *stateNames[] = { _T("UP"), _T("DOWN"), _T("IGNORE"), NULL };
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
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 */
963 static int F_CreateSNMPTransport(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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 {
975 SNMP_Transport *t = node->createSnmpTransport();
976 *ppResult = (t != NULL) ? new NXSL_Value(new NXSL_Object(&g_nxslSnmpTransportClass, t)) : new NXSL_Value;
977 }
978 else
979 {
980 *ppResult = new NXSL_Value;
981 }
982
983 return 0;
984 }
985
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 */
996 static int F_SNMPGet(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
997 {
998 UINT32 len;
999 static UINT32 requestId = 1;
1000 UINT32 varName[MAX_OID_LEN], result = SNMP_ERR_SUCCESS;
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
1013 // Create PDU and send request
1014 size_t nameLen = SNMPParseOID(argv[1]->getValueAsString(&len), varName, MAX_OID_LEN);
1015 if (nameLen == 0)
1016 return NXSL_ERR_BAD_CONDITION;
1017
1018 SNMP_PDU *pdu = new SNMP_PDU(SNMP_GET_REQUEST, requestId++, trans->getSnmpVersion());
1019 pdu->bindVariable(new SNMP_Variable(varName, nameLen));
1020
1021 SNMP_PDU *rspPDU;
1022 result = trans->doRequest(pdu, &rspPDU, SnmpGetDefaultTimeout(), 3);
1023 if (result == SNMP_ERR_SUCCESS)
1024 {
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));
1029 rspPDU->unlinkVariables();
1030 }
1031 else
1032 {
1033 *ppResult = new NXSL_Value;
1034 }
1035 delete rspPDU;
1036 }
1037 else
1038 {
1039 *ppResult = new NXSL_Value;
1040 }
1041 delete pdu;
1042 return 0;
1043 }
1044
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 */
1055 static int F_SNMPGetValue(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
1056 {
1057 TCHAR buffer[4096];
1058 UINT32 len;
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
1071 if (SnmpGetEx(trans, argv[1]->getValueAsString(&len), NULL, 0, buffer, sizeof(buffer), SG_STRING_RESULT, NULL) == SNMP_ERR_SUCCESS)
1072 {
1073 *ppResult = new NXSL_Value(buffer);
1074 }
1075 else
1076 {
1077 *ppResult = new NXSL_Value;
1078 }
1079
1080 return 0;
1081 }
1082
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 */
1095 static int F_SNMPSet(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
1096 {
1097 SNMP_PDU *request = NULL, *response;
1098 UINT32 len;
1099 LONG ret = FALSE;
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 {
1122 var->setValueFromString(ASN_OCTET_STRING, argv[2]->getValueAsString(&len));
1123 }
1124 else
1125 {
1126 UINT32 dataType = SNMPResolveDataType(argv[3]->getValueAsString(&len));
1127 if (dataType == ASN_NULL)
1128 {
1129 DbgPrintf(6, _T("SNMPSet: failed to resolve data type '%s', assume string"),
1130 argv[3]->getValueAsString(&len));
1131 dataType = ASN_OCTET_STRING;
1132 }
1133 var->setValueFromString(dataType, argv[2]->getValueAsString(&len));
1134 }
1135 request->bindVariable(var);
1136 }
1137 else
1138 {
1139 DbgPrintf(6, _T("SNMPSet: Invalid OID: %s"), argv[1]->getValueAsString(&len));
1140 goto finish;
1141 }
1142
1143 // Send request and process response
1144 UINT32 snmpResult;
1145 if ((snmpResult = trans->doRequest(request, &response, SnmpGetDefaultTimeout(), 3)) == SNMP_ERR_SUCCESS)
1146 {
1147 if (response->getErrorCode() != 0)
1148 {
1149 DbgPrintf(6, _T("SNMPSet: operation failed (error code %d)"), response->getErrorCode());
1150 goto finish;
1151 }
1152 else
1153 {
1154 DbgPrintf(6, _T("SNMPSet: success"));
1155 ret = TRUE;
1156 }
1157 delete response;
1158 }
1159 else
1160 {
1161 DbgPrintf(6, _T("SNMPSet: %s"), SNMPGetErrorText(snmpResult));
1162 }
1163
1164 finish:
1165 delete request;
1166 *ppResult = new NXSL_Value(ret);
1167 return 0;
1168 }
1169
1170 /**
1171 * SNMP walk callback
1172 */
1173 static 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
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 */
1189 static int F_SNMPWalk(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
1190 {
1191 if (!argv[0]->isObject())
1192 return NXSL_ERR_NOT_OBJECT;
1193 if (!argv[1]->isString())
1194 return NXSL_ERR_NOT_STRING;
1195
1196 NXSL_Object *obj = argv[0]->getValueAsObject();
1197 if (_tcscmp(obj->getClass()->getName(), g_nxslSnmpTransportClass.getName()))
1198 return NXSL_ERR_BAD_CLASS;
1199
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)
1204 {
1205 *ppResult = new NXSL_Value(varList);
1206 }
1207 else
1208 {
1209 *ppResult = new NXSL_Value;
1210 delete varList;
1211 }
1212 return 0;
1213 }
1214
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 */
1225 static 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
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 */
1270 static int F_AgentReadParameter(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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];
1283 UINT32 rcc = ((Node *)object->getData())->getItemFromAgent(argv[1]->getValueAsCString(), MAX_RESULT_LENGTH, buffer);
1284 if (rcc == DCE_SUCCESS)
1285 *ppResult = new NXSL_Value(buffer);
1286 else
1287 *ppResult = new NXSL_Value;
1288 return 0;
1289 }
1290
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 */
1301 static int F_AgentReadTable(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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
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 */
1332 static 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
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 */
1360 static int F_GetConfigurationVariable(int argc, NXSL_Value **argv, NXSL_Value **ppResult, NXSL_VM *vm)
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
1368 TCHAR buffer[MAX_CONFIG_VALUE];
1369 if (ConfigReadStr(argv[0]->getValueAsCString(), buffer, MAX_CONFIG_VALUE, _T("")))
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
1381 /**
1382 * Get country alpha code from numeric code
1383 */
1384 static 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 */
1397 static 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 */
1410 static 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 */
1423 static 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 */
1435 static 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
1445 /**
1446 * Additional server functions to use within all scripts
1447 */
1448 static NXSL_ExtFunction m_nxslServerFunctions[] =
1449 {
1450 { _T("map"), F_map, -1 },
1451 { _T("mapList"), F_mapList, -1 },
1452 { _T("AgentExecuteAction"), F_AgentExecuteAction, -1 },
1453 { _T("AgentReadList"), F_AgentReadList, 2 },
1454 { _T("AgentReadParameter"), F_AgentReadParameter, 2 },
1455 { _T("AgentReadTable"), F_AgentReadTable, 2 },
1456 { _T("CreateSNMPTransport"), F_CreateSNMPTransport, 1 },
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 },
1462 { _T("DeleteCustomAttribute"), F_DeleteCustomAttribute, 2 },
1463 { _T("EnterMaintenance"), F_EnterMaintenance, 1 },
1464 { _T("GetConfigurationVariable"), F_GetConfigurationVariable, -1 },
1465 { _T("GetCustomAttribute"), F_GetCustomAttribute, 2 },
1466 { _T("GetEventParameter"), F_GetEventParameter, 2 },
1467 { _T("GetInterfaceName"), F_GetInterfaceName, 2 },
1468 { _T("GetInterfaceObject"), F_GetInterfaceObject, 2 },
1469 { _T("GetNodeInterfaces"), F_GetNodeInterfaces, 1 },
1470 { _T("GetNodeParents"), F_GetNodeParents, 1 },
1471 { _T("GetNodeTemplates"), F_GetNodeTemplates, 1 },
1472 { _T("GetObjectChildren"), F_GetObjectChildren, 1 },
1473 { _T("GetObjectParents"), F_GetObjectParents, 1 },
1474 { _T("FindAlarmById"), F_FindAlarmById, 1 },
1475 { _T("FindAlarmByKey"), F_FindAlarmByKey, 1 },
1476 { _T("FindNodeObject"), F_FindNodeObject, 2 },
1477 { _T("FindObject"), F_FindObject, -1 },
1478 { _T("LeaveMaintenance"), F_LeaveMaintenance, 1 },
1479 { _T("ManageObject"), F_ManageObject, 1 },
1480 { _T("PostEvent"), F_PostEvent, -1 },
1481 { _T("RenameObject"), F_RenameObject, 2 },
1482 { _T("SetCustomAttribute"), F_SetCustomAttribute, 3 },
1483 { _T("SetEventParameter"), F_SetEventParameter, 3 },
1484 { _T("SetInterfaceExpectedState"), F_SetInterfaceExpectedState, 2 },
1485 { _T("SNMPGet"), F_SNMPGet, 2 },
1486 { _T("SNMPGetValue"), F_SNMPGetValue, 2 },
1487 { _T("SNMPSet"), F_SNMPSet, -1 /* 3 or 4 */ },
1488 { _T("SNMPWalk"), F_SNMPWalk, 2 },
1489 { _T("UnmanageObject"), F_UnmanageObject, 1 }
1490 };
1491
1492 /**
1493 * Additional server functions to manage objects (disabled by default)
1494 */
1495 static NXSL_ExtFunction m_nxslServerFunctionsForContainers[] =
1496 {
1497 { _T("BindObject"), F_BindObject, 2 },
1498 { _T("CreateContainer"), F_CreateContainer, 2 },
1499 { _T("CreateNode"), F_CreateNode, 3 },
1500 { _T("DeleteObject"), F_DeleteObject, 1 },
1501 { _T("UnbindObject"), F_UnbindObject, 2 }
1502 };
1503
1504 /*** NXSL_ServerEnv class implementation ***/
1505
1506 /**
1507 * Constructor for server default script environment
1508 */
1509 NXSL_ServerEnv::NXSL_ServerEnv() : NXSL_Environment()
1510 {
1511 m_console = NULL;
1512 setLibrary(g_pScriptLibrary);
1513 registerFunctionSet(sizeof(m_nxslServerFunctions) / sizeof(NXSL_ExtFunction), m_nxslServerFunctions);
1514 RegisterDCIFunctions(this);
1515 registerFunctionSet(g_nxslNumSituationFunctions, g_nxslSituationFunctions);
1516 if (g_flags & AF_ENABLE_NXSL_CONTAINER_FUNCS)
1517 registerFunctionSet(sizeof(m_nxslServerFunctionsForContainers) / sizeof(NXSL_ExtFunction), m_nxslServerFunctionsForContainers);
1518 // Pass event to modules
1519 CALL_ALL_MODULES(pfNXSLServerEnvConfig, (this));
1520 }
1521
1522 /**
1523 * Script trace output
1524 */
1525 void 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 }
1535 }
1536
1537 /**
1538 * Print script output to console
1539 */
1540 void 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 }
1548
1549 /**
1550 * Additional VM configuration
1551 */
1552 void NXSL_ServerEnv::configureVM(NXSL_VM *vm)
1553 {
1554 CALL_ALL_MODULES(pfNXSLServerVMConfig, (vm));
1555 }
1556
1557 /**
1558 * Constructor for environment intended for passing script's output to client
1559 */
1560 NXSL_ClientSessionEnv::NXSL_ClientSessionEnv(ClientSession *session, NXCPMessage *response) : NXSL_ServerEnv()
1561 {
1562 m_session = session;
1563 m_response = response;
1564 }
1565
1566 /**
1567 * Send script output to user
1568 */
1569 void NXSL_ClientSessionEnv::print(NXSL_Value *value)
1570 {
1571 if (m_session != NULL && m_response != NULL)
1572 {
1573 const TCHAR *text = value->getValueAsCString();
1574 m_response->setField(VID_MESSAGE, text);
1575 m_session->sendMessage(m_response);
1576 }
1577 }
1578
1579 /**
1580 * Trace output
1581 */
1582 void NXSL_ClientSessionEnv::trace(int level, const TCHAR *text)
1583 {
1584 if (m_session != NULL && m_response != NULL)
1585 {
1586 size_t len = _tcslen(text);
1587 TCHAR *t = (TCHAR *)malloc((len + 2) * sizeof(TCHAR));
1588 memcpy(t, text, len * sizeof(TCHAR));
1589 t[len] = _T('\n');
1590 t[len + 1] = 0;
1591 m_response->setField(VID_MESSAGE, t);
1592 m_session->sendMessage(m_response);
1593 free(t);
1594 }
1595 NXSL_ServerEnv::trace(level, text);
1596 }
1597
1598 /**
1599 * Call hook script
1600 */
1601 NXSL_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 }