1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxserver.h"
24
25 #include "actions.h"
26 #include "operations.h"
27 #include "events.h"
28 #include "zbxregexp.h"
29
30 /******************************************************************************
31 * *
32 * Function: compare_events *
33 * *
34 * Purpose: compare events by objectid *
35 * *
36 * Parameters: d1 - [IN] event structure to compare to d2 *
37 * d2 - [IN] event structure to compare to d1 *
38 * *
39 * Return value: 0 - equal *
40 * not 0 - otherwise *
41 * *
42 ******************************************************************************/
compare_events(const void * d1,const void * d2)43 static int compare_events(const void *d1, const void *d2)
44 {
45 const DB_EVENT *p1 = *(const DB_EVENT **)d1;
46 const DB_EVENT *p2 = *(const DB_EVENT **)d2;
47
48 ZBX_RETURN_IF_NOT_EQUAL(p1->objectid, p2->objectid);
49 ZBX_RETURN_IF_NOT_EQUAL(p1->object, p2->object);
50
51 return 0;
52 }
53
54 /******************************************************************************
55 * *
56 * Function: add_condition_match *
57 * *
58 * Purpose: save eventids that match condition *
59 * *
60 * Parameters: esc_events - [IN] events to check *
61 * condition - [IN/OUT] condition for matching, outputs *
62 * event ids that match condition *
63 * objectid - [IN] object id, for example trigger or item id *
64 * object - [IN] object, for example EVENT_OBJECT_TRIGGER *
65 ******************************************************************************/
add_condition_match(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition,zbx_uint64_t objectid,int object)66 static void add_condition_match(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition,
67 zbx_uint64_t objectid, int object)
68 {
69 int index;
70 const DB_EVENT event_search = {.objectid = objectid, .object = object};
71
72 if (FAIL != (index = zbx_vector_ptr_bsearch(esc_events, &event_search, compare_events)))
73 {
74 const DB_EVENT *event = (DB_EVENT *)esc_events->values[index];
75 int i;
76
77 zbx_vector_uint64_append(&condition->eventids, event->eventid);
78
79 for (i = index - 1; 0 <= i; i--)
80 {
81 event = esc_events->values[i];
82
83 if (event->objectid != objectid || event->object != object)
84 break;
85
86 zbx_vector_uint64_append(&condition->eventids, event->eventid);
87 }
88
89 for (i = index + 1; i < esc_events->values_num; i++)
90 {
91 event = (DB_EVENT *)esc_events->values[i];
92
93 if (event->objectid != objectid || event->object != object)
94 break;
95
96 zbx_vector_uint64_append(&condition->eventids, event->eventid);
97 }
98 }
99 }
100
101 /******************************************************************************
102 * *
103 * Function: get_object_ids *
104 * *
105 * Purpose: get objectids of escalation events *
106 * *
107 * Parameters: esc_events [IN] - events to check *
108 * objectids [OUT] - event objectids to be used in condition *
109 * allocation *
110 * *
111 ******************************************************************************/
get_object_ids(const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids)112 static void get_object_ids(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids)
113 {
114 int i;
115
116 zbx_vector_uint64_reserve(objectids, esc_events->values_num);
117
118 for (i = 0; i < esc_events->values_num; i++)
119 {
120 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
121
122 zbx_vector_uint64_append(objectids, event->objectid);
123 }
124
125 zbx_vector_uint64_uniq(objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
126 }
127
128 /******************************************************************************
129 * *
130 * Function: check_host_group_condition *
131 * *
132 * Purpose: check host group condition *
133 * *
134 * Parameters: esc_events - [IN] events to check *
135 * condition - [IN/OUT] condition for matching, outputs *
136 * event ids that match condition *
137 * *
138 * Return value: SUCCEED - supported operator *
139 * NOTSUPPORTED - not supported operator *
140 * *
141 ******************************************************************************/
check_host_group_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)142 static int check_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
143 {
144 char *sql = NULL;
145 size_t sql_alloc = 0, sql_offset = 0;
146 DB_RESULT result;
147 DB_ROW row;
148 zbx_vector_uint64_t objectids, groupids;
149 zbx_uint64_t condition_value;
150
151 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
152 return NOTSUPPORTED;
153
154 ZBX_STR2UINT64(condition_value, condition->value);
155
156 zbx_vector_uint64_create(&objectids);
157 zbx_vector_uint64_create(&groupids);
158
159 get_object_ids(esc_events, &objectids);
160 zbx_dc_get_nested_hostgroupids(&condition_value, 1, &groupids);
161
162 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
163 "select distinct f.triggerid"
164 " from hosts_groups hg,hosts h,items i,functions f"
165 " where hg.hostid=h.hostid"
166 " and h.hostid=i.hostid"
167 " and i.itemid=f.itemid"
168 " and");
169
170 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid",
171 objectids.values, objectids.values_num);
172
173 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and");
174 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.groupid", groupids.values, groupids.values_num);
175
176 result = DBselect("%s", sql);
177
178 while (NULL != (row = DBfetch(result)))
179 {
180 zbx_uint64_t objectid;
181
182 ZBX_STR2UINT64(objectid, row[0]);
183 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
184 {
185 int index;
186
187 if (FAIL != (index = zbx_vector_uint64_search(&objectids, objectid,
188 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
189 {
190 zbx_vector_uint64_remove_noorder(&objectids, index);
191 }
192 }
193 else
194 add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER);
195
196 }
197 DBfree_result(result);
198
199 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
200 {
201 int i;
202
203 for (i = 0; i < objectids.values_num; i++)
204 add_condition_match(esc_events, condition, objectids.values[i], EVENT_OBJECT_TRIGGER);
205 }
206
207 zbx_vector_uint64_destroy(&groupids);
208 zbx_vector_uint64_destroy(&objectids);
209 zbx_free(sql);
210
211 return SUCCEED;
212 }
213
214 /******************************************************************************
215 * *
216 * Function: trigger_parents_sql_alloc *
217 * *
218 * Purpose: mapping between discovered triggers and their prototypes *
219 * *
220 * Parameters: sql [IN/OUT] - allocated sql query *
221 * sql_alloc [IN/OUT] - how much bytes allocated *
222 * objectids_tmp [IN/OUT] - uses to allocate query *
223 * *
224 * *
225 ******************************************************************************/
trigger_parents_sql_alloc(char ** sql,size_t * sql_alloc,zbx_vector_uint64_t * objectids_tmp)226 static void trigger_parents_sql_alloc(char **sql, size_t *sql_alloc, zbx_vector_uint64_t *objectids_tmp)
227 {
228 size_t sql_offset = 0;
229
230 zbx_snprintf_alloc(sql, sql_alloc, &sql_offset,
231 "select triggerid,parent_triggerid"
232 " from trigger_discovery"
233 " where");
234
235 DBadd_condition_alloc(sql, sql_alloc, &sql_offset, "triggerid", objectids_tmp->values,
236 objectids_tmp->values_num);
237 }
238
239 /******************************************************************************
240 * *
241 * Function: objectids_to_pair *
242 * *
243 * Purpose: copy objects to pair, for hierarchy checks *
244 * *
245 * Parameters: objectids [IN] - objects *
246 * objectids_pair [OUT] - objectids will be copied here *
247 * *
248 ******************************************************************************/
objectids_to_pair(zbx_vector_uint64_t * objectids,zbx_vector_uint64_pair_t * objectids_pair)249 static void objectids_to_pair(zbx_vector_uint64_t *objectids, zbx_vector_uint64_pair_t *objectids_pair)
250 {
251 int i;
252
253 zbx_vector_uint64_pair_reserve(objectids_pair, objectids->values_num);
254
255 for (i = 0; i < objectids->values_num; i++)
256 {
257 zbx_uint64_pair_t pair = {objectids->values[i], objectids->values[i]};
258
259 zbx_vector_uint64_pair_append(objectids_pair, pair);
260 }
261 }
262
263 /******************************************************************************
264 * *
265 * Function: check_object_hierarchy *
266 * *
267 * Purpose: there can be multiple levels of templates, that need *
268 * resolving in order to compare to condition *
269 * *
270 * Parameters: object - [IN] type of the object that generated event *
271 * Parameters: esc_events - [IN] events being checked *
272 * objectids - [IN] object ids of the esc_events *
273 * (contents can be changed by processing *
274 * and should not be used by caller) *
275 * objectids_pair - [IN] pairs of (objectid, source objectid) *
276 * where objectid are ids of the esc_events*
277 * and source objectid is object id for *
278 * normal objects and prototype id for *
279 * discovered objects *
280 * (contents can be changed by processing *
281 * and should not be used by caller) *
282 * condition - [IN/OUT] condition to evaluate, matched *
283 * events will be added to condition *
284 * eventids vector *
285 * condition_value - [IN] condition value for matching *
286 * sql_str - [IN] custom sql query, must obtain object, *
287 * template object id and value *
288 * sql_field - [IN] field name that is added to the sql *
289 * query condition *
290 * *
291 ******************************************************************************/
check_object_hierarchy(int object,const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids,zbx_vector_uint64_pair_t * objectids_pair,zbx_condition_t * condition,zbx_uint64_t condition_value,char * sql_str,char * sql_field)292 static void check_object_hierarchy(int object, const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids,
293 zbx_vector_uint64_pair_t *objectids_pair, zbx_condition_t *condition, zbx_uint64_t condition_value,
294 char *sql_str, char *sql_field)
295 {
296 int i;
297 zbx_vector_uint64_t objectids_tmp;
298 zbx_vector_uint64_pair_t objectids_pair_tmp;
299 char *sql = NULL;
300 size_t sql_alloc = 0;
301
302 zbx_vector_uint64_pair_create(&objectids_pair_tmp);
303 zbx_vector_uint64_create(&objectids_tmp);
304 zbx_vector_uint64_reserve(&objectids_tmp, objectids_pair->values_num);
305
306 while (0 != objectids_pair->values_num)
307 {
308 DB_RESULT result;
309 DB_ROW row;
310 size_t sql_offset = 0;
311
312 /* objectids that need parents to be determined */
313 for (i = 0; i < objectids_pair->values_num; i++)
314 zbx_vector_uint64_append(&objectids_tmp, objectids_pair->values[i].second);
315
316 zbx_vector_uint64_sort(&objectids_tmp, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
317 /* multiple hosts can share trigger from same template, don't allocate duplicate ids */
318 zbx_vector_uint64_uniq(&objectids_tmp, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
319
320 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, sql_str);
321
322 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, sql_field, objectids_tmp.values,
323 objectids_tmp.values_num);
324
325 zbx_vector_uint64_clear(&objectids_tmp);
326
327 result = DBselect("%s", sql);
328
329 while (NULL != (row = DBfetch(result)))
330 {
331 zbx_uint64_t objectid, parent_objectid, value;
332
333 ZBX_STR2UINT64(objectid, row[0]);
334 ZBX_STR2UINT64(parent_objectid, row[1]);
335 ZBX_STR2UINT64(value, row[2]);
336
337 /* find all templates or trigger ids that match our condition and get original id */
338 for (i = 0; i < objectids_pair->values_num; i++)
339 {
340 /* objectid is id that has template id, that match condition */
341 /* second are those that we did select on */
342 if (objectids_pair->values[i].second != objectid)
343 continue;
344
345 if (value == condition_value)
346 {
347 if (CONDITION_OPERATOR_EQUAL != condition->op)
348 {
349 int j;
350
351 /* remove equals from result set, leaving only not equals */
352 if (FAIL != (j = zbx_vector_uint64_search(objectids,
353 objectids_pair->values[i].first,
354 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
355 {
356 zbx_vector_uint64_remove_noorder(objectids, j);
357 }
358 }
359 else
360 {
361 add_condition_match(esc_events, condition,
362 objectids_pair->values[i].first, object);
363 }
364 }
365 else
366 {
367 /* update template id to next level, to compare to condition in next select */
368
369 objectids_pair->values[i].second = parent_objectid;
370 zbx_vector_uint64_pair_append(&objectids_pair_tmp, objectids_pair->values[i]);
371 }
372
373 objectids_pair->values[i].second = 0;
374 }
375 }
376 zbx_free(sql);
377 DBfree_result(result);
378
379 /* resolve in next select only those triggerids that have template id and not equal to condition */
380 zbx_vector_uint64_pair_clear(objectids_pair);
381
382 if (0 != objectids_pair_tmp.values_num)
383 {
384 zbx_vector_uint64_pair_append_array(objectids_pair, objectids_pair_tmp.values,
385 objectids_pair_tmp.values_num);
386 }
387
388 zbx_vector_uint64_pair_clear(&objectids_pair_tmp);
389 }
390
391 /* equals are deleted so copy to result those that are left (not equals) */
392 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
393 {
394 for (i = 0; i < objectids->values_num; i++)
395 add_condition_match(esc_events, condition, objectids->values[i], object);
396 }
397
398 zbx_vector_uint64_pair_destroy(&objectids_pair_tmp);
399 zbx_vector_uint64_destroy(&objectids_tmp);
400 }
401
402 /******************************************************************************
403 * *
404 * Function: check_host_template_condition *
405 * *
406 * Purpose: check host template condition *
407 * *
408 * Parameters: esc_events - [IN] events to check *
409 * condition - [IN/OUT] condition for matching, outputs *
410 * event ids that match condition *
411 * *
412 * Return value: SUCCEED - supported operator *
413 * NOTSUPPORTED - not supported operator *
414 * *
415 ******************************************************************************/
check_host_template_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)416 static int check_host_template_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
417 {
418 char *sql = NULL;
419 size_t sql_alloc = 0;
420 DB_RESULT result;
421 DB_ROW row;
422 zbx_uint64_t condition_value;
423 zbx_vector_uint64_t objectids;
424 zbx_vector_uint64_pair_t objectids_pair;
425
426 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
427 return NOTSUPPORTED;
428
429 zbx_vector_uint64_create(&objectids);
430 zbx_vector_uint64_pair_create(&objectids_pair);
431
432 get_object_ids(esc_events, &objectids);
433 objectids_to_pair(&objectids, &objectids_pair);
434
435 ZBX_STR2UINT64(condition_value, condition->value);
436
437 trigger_parents_sql_alloc(&sql, &sql_alloc, &objectids);
438
439 result = DBselect("%s", sql);
440
441 while (NULL != (row = DBfetch(result)))
442 {
443 zbx_uint64_pair_t pair;
444 int i;
445
446 ZBX_STR2UINT64(pair.first, row[0]);
447
448 if (FAIL != (i = zbx_vector_uint64_pair_search(&objectids_pair, pair, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
449 ZBX_STR2UINT64(objectids_pair.values[i].second, row[1]);
450 }
451 DBfree_result(result);
452
453 check_object_hierarchy(EVENT_OBJECT_TRIGGER, esc_events, &objectids, &objectids_pair, condition, condition_value,
454 "select distinct t.triggerid,t.templateid,i.hostid"
455 " from items i,functions f,triggers t"
456 " where i.itemid=f.itemid"
457 " and f.triggerid=t.templateid"
458 " and",
459 "t.triggerid");
460
461 zbx_vector_uint64_destroy(&objectids);
462 zbx_vector_uint64_pair_destroy(&objectids_pair);
463 zbx_free(sql);
464
465 return SUCCEED;
466 }
467
468 /******************************************************************************
469 * *
470 * Function: check_host_condition *
471 * *
472 * Purpose: check host condition *
473 * *
474 * Parameters: esc_events - [IN] events to check *
475 * condition - [IN/OUT] condition for matching, outputs *
476 * event ids that match condition *
477 * *
478 * Return value: SUCCEED - supported operator *
479 * NOTSUPPORTED - not supported operator *
480 * *
481 ******************************************************************************/
check_host_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)482 static int check_host_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
483 {
484 char *sql = NULL, *operation;
485 size_t sql_alloc = 0, sql_offset = 0;
486 DB_RESULT result;
487 DB_ROW row;
488 zbx_vector_uint64_t objectids;
489 zbx_uint64_t condition_value;
490
491 if (CONDITION_OPERATOR_EQUAL == condition->op)
492 operation = " and";
493 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
494 operation = " and not";
495 else
496 return NOTSUPPORTED;
497
498 ZBX_STR2UINT64(condition_value, condition->value);
499
500 zbx_vector_uint64_create(&objectids);
501
502 get_object_ids(esc_events, &objectids);
503
504 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
505 "select distinct f.triggerid"
506 " from items i,functions f"
507 " where i.itemid=f.itemid"
508 "%s i.hostid=" ZBX_FS_UI64
509 " and",
510 operation,
511 condition_value);
512
513 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", objectids.values, objectids.values_num);
514
515 result = DBselect("%s", sql);
516
517 while (NULL != (row = DBfetch(result)))
518 {
519 zbx_uint64_t objectid;
520
521 ZBX_STR2UINT64(objectid, row[0]);
522 add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER);
523 }
524 DBfree_result(result);
525
526 zbx_vector_uint64_destroy(&objectids);
527 zbx_free(sql);
528
529 return SUCCEED;
530 }
531
532 /******************************************************************************
533 * *
534 * Function: check_trigger_id_condition *
535 * *
536 * Purpose: check trigger id condition *
537 * *
538 * Parameters: esc_events - [IN] events to check *
539 * condition - [IN/OUT] condition for matching, outputs *
540 * event ids that match condition *
541 * *
542 * Return value: SUCCEED - supported operator *
543 * NOTSUPPORTED - not supported operator *
544 * *
545 ******************************************************************************/
check_trigger_id_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)546 static int check_trigger_id_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
547 {
548 zbx_uint64_t condition_value;
549 zbx_vector_uint64_t objectids;
550 zbx_vector_uint64_pair_t objectids_pair;
551 int i;
552
553 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
554 return NOTSUPPORTED;
555
556 ZBX_STR2UINT64(condition_value, condition->value);
557
558 zbx_vector_uint64_create(&objectids);
559 zbx_vector_uint64_pair_create(&objectids_pair);
560
561 for (i = 0; i < esc_events->values_num; i++)
562 {
563 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
564
565 if (event->objectid == condition_value)
566 {
567 if (CONDITION_OPERATOR_EQUAL == condition->op)
568 zbx_vector_uint64_append(&condition->eventids, event->eventid);
569 }
570 else
571 zbx_vector_uint64_append(&objectids, event->objectid);
572 }
573
574 if (0 != objectids.values_num)
575 {
576 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
577 objectids_to_pair(&objectids, &objectids_pair);
578
579 check_object_hierarchy(EVENT_OBJECT_TRIGGER, esc_events, &objectids, &objectids_pair, condition, condition_value,
580 "select triggerid,templateid,templateid"
581 " from triggers"
582 " where templateid is not null and",
583 "triggerid");
584 }
585
586 zbx_vector_uint64_destroy(&objectids);
587 zbx_vector_uint64_pair_destroy(&objectids_pair);
588
589 return SUCCEED;
590 }
591
592 /******************************************************************************
593 * *
594 * Function: check_trigger_name_condition *
595 * *
596 * Purpose: check trigger name condition *
597 * *
598 * Parameters: esc_events - [IN] events to check *
599 * condition - [IN/OUT] condition for matching, outputs *
600 * event ids that match condition *
601 * *
602 * Return value: SUCCEED - supported operator *
603 * NOTSUPPORTED - not supported operator *
604 * *
605 ******************************************************************************/
check_trigger_name_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)606 static int check_trigger_name_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
607 {
608 int i;
609
610 if (CONDITION_OPERATOR_LIKE != condition->op && CONDITION_OPERATOR_NOT_LIKE != condition->op)
611 return NOTSUPPORTED;
612
613 for (i = 0; i < esc_events->values_num; i++)
614 {
615 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
616
617 switch (condition->op)
618 {
619 case CONDITION_OPERATOR_LIKE:
620 if (NULL != strstr(event->name, condition->value))
621 zbx_vector_uint64_append(&condition->eventids, event->eventid);
622 break;
623 case CONDITION_OPERATOR_NOT_LIKE:
624 if (NULL == strstr(event->name, condition->value))
625 zbx_vector_uint64_append(&condition->eventids, event->eventid);
626 break;
627 }
628 }
629
630 return SUCCEED;
631 }
632
633 /******************************************************************************
634 * *
635 * Function: check_trigger_severity_condition *
636 * *
637 * Purpose: check trigger severity condition *
638 * *
639 * Parameters: esc_events - [IN] events to check *
640 * condition - [IN/OUT] condition for matching, outputs *
641 * event ids that match condition *
642 * *
643 * Return value: SUCCEED - supported operator *
644 * NOTSUPPORTED - not supported operator *
645 * *
646 ******************************************************************************/
check_trigger_severity_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)647 static int check_trigger_severity_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
648 {
649 unsigned char condition_value;
650 int i;
651
652 condition_value = (unsigned char)atoi(condition->value);
653
654 for (i = 0; i < esc_events->values_num; i++)
655 {
656 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
657
658 switch (condition->op)
659 {
660 case CONDITION_OPERATOR_EQUAL:
661 if (event->trigger.priority == condition_value)
662 zbx_vector_uint64_append(&condition->eventids, event->eventid);
663 break;
664 case CONDITION_OPERATOR_NOT_EQUAL:
665 if (event->trigger.priority != condition_value)
666 zbx_vector_uint64_append(&condition->eventids, event->eventid);
667 break;
668 case CONDITION_OPERATOR_MORE_EQUAL:
669 if (event->trigger.priority >= condition_value)
670 zbx_vector_uint64_append(&condition->eventids, event->eventid);
671 break;
672 case CONDITION_OPERATOR_LESS_EQUAL:
673 if (event->trigger.priority <= condition_value)
674 zbx_vector_uint64_append(&condition->eventids, event->eventid);
675 break;
676 default:
677 return NOTSUPPORTED;
678 }
679 }
680
681 return SUCCEED;
682 }
683
684 /******************************************************************************
685 * *
686 * Function: check_time_period_condition *
687 * *
688 * Purpose: check time period condition *
689 * *
690 * Parameters: esc_events - [IN] events to check *
691 * condition - [IN/OUT] condition for matching, outputs *
692 * event ids that match condition *
693 * *
694 * Return value: SUCCEED - supported operator *
695 * NOTSUPPORTED - not supported operator *
696 * *
697 ******************************************************************************/
check_time_period_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)698 static int check_time_period_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
699 {
700 char *period;
701 int i;
702
703 if (CONDITION_OPERATOR_IN != condition->op && CONDITION_OPERATOR_NOT_IN != condition->op)
704 return NOTSUPPORTED;
705
706 period = zbx_strdup(NULL, condition->value);
707 substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &period,
708 MACRO_TYPE_COMMON, NULL, 0);
709
710 for (i = 0; i < esc_events->values_num; i++)
711 {
712 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
713 int res;
714
715 if (SUCCEED == zbx_check_time_period(period, (time_t)event->clock, NULL, &res))
716 {
717 switch (condition->op)
718 {
719 case CONDITION_OPERATOR_IN:
720 if (SUCCEED == res)
721 zbx_vector_uint64_append(&condition->eventids, event->eventid);
722 break;
723 case CONDITION_OPERATOR_NOT_IN:
724 if (FAIL == res)
725 zbx_vector_uint64_append(&condition->eventids, event->eventid);
726 break;
727 }
728 }
729 else
730 {
731 zabbix_log(LOG_LEVEL_WARNING, "Invalid time period \"%s\" for condition id [" ZBX_FS_UI64 "]",
732 period, condition->conditionid);
733 }
734 }
735
736 zbx_free(period);
737
738 return SUCCEED;
739 }
740
check_suppressed_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)741 static int check_suppressed_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
742 {
743 int i;
744
745 for (i = 0; i < esc_events->values_num; i++)
746 {
747 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
748
749 switch (condition->op)
750 {
751 case CONDITION_OPERATOR_YES:
752 if (ZBX_PROBLEM_SUPPRESSED_TRUE == event->suppressed)
753 zbx_vector_uint64_append(&condition->eventids, event->eventid);
754 break;
755 case CONDITION_OPERATOR_NO:
756 if (ZBX_PROBLEM_SUPPRESSED_FALSE == event->suppressed)
757 zbx_vector_uint64_append(&condition->eventids, event->eventid);
758 break;
759 default:
760 return NOTSUPPORTED;
761 }
762 }
763
764 return SUCCEED;
765 }
766
check_acknowledged_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)767 static int check_acknowledged_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
768 {
769 int i;
770 zbx_vector_uint64_t eventids;
771 char *sql = NULL;
772 size_t sql_alloc = 0, sql_offset = 0;
773 DB_RESULT result;
774 DB_ROW row;
775 int ret = SUCCEED;
776
777 zbx_vector_uint64_create(&eventids);
778 zbx_vector_uint64_reserve(&eventids, esc_events->values_num);
779
780 for (i = 0; i < esc_events->values_num; i++)
781 {
782 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
783
784 zbx_vector_uint64_append(&eventids, event->eventid);
785 }
786
787 zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
788
789 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
790 "select eventid"
791 " from events"
792 " where acknowledged=%d"
793 " and",
794 atoi(condition->value));
795
796 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "eventid", eventids.values, eventids.values_num);
797
798 result = DBselect("%s", sql);
799 while (NULL != (row = DBfetch(result)))
800 {
801 zbx_uint64_t eventid;
802
803 ZBX_STR2UINT64(eventid, row[0]);
804 switch (condition->op)
805 {
806 case CONDITION_OPERATOR_EQUAL:
807 zbx_vector_uint64_append(&condition->eventids, eventid);
808 break;
809 default:
810 ret = NOTSUPPORTED;
811 }
812
813 }
814 DBfree_result(result);
815 zbx_free(sql);
816
817 zbx_vector_uint64_destroy(&eventids);
818
819 return ret;
820 }
821
822 /******************************************************************************
823 * *
824 * Function: check_condition_event_tag *
825 * *
826 * Purpose: check condition event tag *
827 * *
828 * Parameters: esc_events - [IN] events to check *
829 * condition - [IN/OUT] condition for matching, outputs *
830 * event ids that match condition *
831 * *
832 ******************************************************************************/
check_condition_event_tag(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)833 static void check_condition_event_tag(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
834 {
835 int i, ret, ret_continue;
836
837 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op || CONDITION_OPERATOR_NOT_LIKE == condition->op)
838 ret_continue = SUCCEED;
839 else
840 ret_continue = FAIL;
841
842 for (i = 0; i < esc_events->values_num; i++)
843 {
844 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
845 int j;
846
847 ret = ret_continue;
848
849 for (j = 0; j < event->tags.values_num && ret == ret_continue; j++)
850 {
851 const zbx_tag_t *tag = (zbx_tag_t *)event->tags.values[j];
852
853 ret = zbx_strmatch_condition(tag->tag, condition->value, condition->op);
854 }
855
856 if (SUCCEED == ret)
857 zbx_vector_uint64_append(&condition->eventids, event->eventid);
858 }
859 }
860
861 /******************************************************************************
862 * *
863 * Function: check_condition_event_tag_value *
864 * *
865 * Purpose: check condition event tag value *
866 * *
867 * Parameters: esc_events - [IN] events to check *
868 * condition - [IN/OUT] condition for matching, outputs *
869 * event ids that match condition *
870 * *
871 ******************************************************************************/
check_condition_event_tag_value(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)872 static void check_condition_event_tag_value(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
873 {
874 int i, ret, ret_continue;
875
876 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op || CONDITION_OPERATOR_NOT_LIKE == condition->op)
877 ret_continue = SUCCEED;
878 else
879 ret_continue = FAIL;
880
881 for (i = 0; i < esc_events->values_num; i++)
882 {
883 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
884 int j;
885
886 ret = ret_continue;
887
888 for (j = 0; j < event->tags.values_num && ret == ret_continue; j++)
889 {
890 zbx_tag_t *tag = (zbx_tag_t *)event->tags.values[j];
891
892 if (0 == strcmp(condition->value2, tag->tag))
893 ret = zbx_strmatch_condition(tag->value, condition->value, condition->op);
894 }
895
896 if (SUCCEED == ret)
897 zbx_vector_uint64_append(&condition->eventids, event->eventid);
898 }
899 }
900
901 /******************************************************************************
902 * *
903 * Function: check_trigger_condition *
904 * *
905 * Purpose: check if event matches single condition *
906 * *
907 * Parameters: event - trigger event to check *
908 * (event->source == EVENT_SOURCE_TRIGGERS) *
909 * condition - condition for matching *
910 * *
911 * Return value: SUCCEED - matches, FAIL - otherwise *
912 * *
913 * Author: Alexei Vladishev *
914 * *
915 ******************************************************************************/
check_trigger_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)916 static void check_trigger_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
917 {
918 int ret;
919
920 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
921
922 switch (condition->conditiontype)
923 {
924 case CONDITION_TYPE_HOST_GROUP:
925 ret = check_host_group_condition(esc_events, condition);
926 break;
927 case CONDITION_TYPE_HOST_TEMPLATE:
928 ret = check_host_template_condition(esc_events, condition);
929 break;
930 case CONDITION_TYPE_HOST:
931 ret = check_host_condition(esc_events, condition);
932 break;
933 case CONDITION_TYPE_TRIGGER:
934 ret = check_trigger_id_condition(esc_events, condition);
935 break;
936 case CONDITION_TYPE_TRIGGER_NAME:
937 ret = check_trigger_name_condition(esc_events, condition);
938 break;
939 case CONDITION_TYPE_TRIGGER_SEVERITY:
940 ret = check_trigger_severity_condition(esc_events, condition);
941 break;
942 case CONDITION_TYPE_TIME_PERIOD:
943 ret = check_time_period_condition(esc_events, condition);
944 break;
945 case CONDITION_TYPE_SUPPRESSED:
946 ret = check_suppressed_condition(esc_events, condition);
947 break;
948 case CONDITION_TYPE_EVENT_ACKNOWLEDGED:
949 ret = check_acknowledged_condition(esc_events, condition);
950 break;
951 case CONDITION_TYPE_EVENT_TAG:
952 check_condition_event_tag(esc_events, condition);
953 ret = SUCCEED;
954 break;
955 case CONDITION_TYPE_EVENT_TAG_VALUE:
956 check_condition_event_tag_value(esc_events,condition);
957 ret = SUCCEED;
958 break;
959 default:
960 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
961 (int)condition->conditiontype, condition->conditionid);
962 ret = FAIL;
963 }
964
965 if (NOTSUPPORTED == ret)
966 {
967 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
968 (int)condition->op, condition->conditionid);
969 }
970
971 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
972 }
973
974 /******************************************************************************
975 * *
976 * Function: get_object_ids_discovery *
977 * *
978 * Purpose: get objectids for dhost *
979 * *
980 * Parameters: esc_events - [IN] events to check *
981 * objectids - [OUT] event objectids to be used in condition *
982 * allocation 2 vectors where first one is *
983 * dhost ids, second is dservice *
984 * *
985 ******************************************************************************/
get_object_ids_discovery(const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids)986 static void get_object_ids_discovery(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids)
987 {
988 int i;
989
990 for (i = 0; i < esc_events->values_num; i++)
991 {
992 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
993
994 if (event->object == EVENT_OBJECT_DHOST)
995 zbx_vector_uint64_append(&objectids[0], event->objectid);
996 else
997 zbx_vector_uint64_append(&objectids[1], event->objectid);
998 }
999
1000 zbx_vector_uint64_uniq(&objectids[0], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1001 zbx_vector_uint64_uniq(&objectids[1], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1002 }
1003 /******************************************************************************
1004 * *
1005 * Function: check_drule_condition *
1006 * *
1007 * Purpose: check discovery rule condition *
1008 * *
1009 * Parameters: esc_events - [IN] events to check *
1010 * condition - [IN/OUT] condition for matching, outputs *
1011 * event ids that match condition *
1012 * *
1013 * Return value: SUCCEED - supported operator *
1014 * NOTSUPPORTED - not supported operator *
1015 * *
1016 ******************************************************************************/
check_drule_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1017 static int check_drule_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1018 {
1019 char *sql = NULL, *operation_and, *operation_where;
1020 size_t sql_alloc = 0, i;
1021 DB_RESULT result;
1022 DB_ROW row;
1023 int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1024 zbx_vector_uint64_t objectids[2];
1025 zbx_uint64_t condition_value;
1026
1027 if (CONDITION_OPERATOR_EQUAL == condition->op)
1028 {
1029 operation_and = " and";
1030 operation_where = " where";
1031 }
1032 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1033 {
1034 operation_and = " and not";
1035 operation_where = " where not";
1036 }
1037 else
1038 return NOTSUPPORTED;
1039
1040 ZBX_STR2UINT64(condition_value, condition->value);
1041
1042 zbx_vector_uint64_create(&objectids[0]);
1043 zbx_vector_uint64_create(&objectids[1]);
1044
1045 get_object_ids_discovery(esc_events, objectids);
1046
1047 for (i = 0; i < (int)ARRSIZE(objects); i++)
1048 {
1049 size_t sql_offset = 0;
1050
1051 if (0 == objectids[i].values_num)
1052 continue;
1053
1054 if (EVENT_OBJECT_DHOST == objects[i])
1055 {
1056 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1057 "select dhostid"
1058 " from dhosts"
1059 "%s druleid=" ZBX_FS_UI64
1060 " and",
1061 operation_where,
1062 condition_value);
1063
1064 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid",
1065 objectids[i].values, objectids[i].values_num);
1066 }
1067 else /* EVENT_OBJECT_DSERVICE */
1068 {
1069 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1070 "select s.dserviceid"
1071 " from dhosts h,dservices s"
1072 " where h.dhostid=s.dhostid"
1073 "%s h.druleid=" ZBX_FS_UI64
1074 " and",
1075 operation_and,
1076 condition_value);
1077
1078 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.dserviceid",
1079 objectids[i].values, objectids[i].values_num);
1080 }
1081
1082 result = DBselect("%s", sql);
1083
1084 while (NULL != (row = DBfetch(result)))
1085 {
1086 zbx_uint64_t objectid;
1087
1088 ZBX_STR2UINT64(objectid, row[0]);
1089 add_condition_match(esc_events, condition, objectid, objects[i]);
1090 }
1091 DBfree_result(result);
1092 }
1093
1094 zbx_vector_uint64_destroy(&objectids[0]);
1095 zbx_vector_uint64_destroy(&objectids[1]);
1096 zbx_free(sql);
1097
1098 return SUCCEED;
1099 }
1100
1101 /******************************************************************************
1102 * *
1103 * Function: check_dcheck_condition *
1104 * *
1105 * Purpose: check discovery check condition *
1106 * *
1107 * Parameters: esc_events - [IN] events to check *
1108 * condition - [IN/OUT] condition for matching, outputs *
1109 * event ids that match condition *
1110 * *
1111 * Return value: SUCCEED - supported operator *
1112 * NOTSUPPORTED - not supported operator *
1113 * *
1114 ******************************************************************************/
check_dcheck_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1115 static int check_dcheck_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1116 {
1117 char *sql = NULL, *operation_where;
1118 size_t sql_alloc = 0, sql_offset = 0;
1119 DB_RESULT result;
1120 DB_ROW row;
1121 int object = EVENT_OBJECT_DSERVICE, i;
1122 zbx_vector_uint64_t objectids;
1123 zbx_uint64_t condition_value;
1124
1125 if (CONDITION_OPERATOR_EQUAL == condition->op)
1126 operation_where = " where";
1127 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1128 operation_where = " where not";
1129 else
1130 return NOTSUPPORTED;
1131
1132 ZBX_STR2UINT64(condition_value, condition->value);
1133
1134 zbx_vector_uint64_create(&objectids);
1135
1136 for (i = 0; i < esc_events->values_num; i++)
1137 {
1138 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1139
1140 if (object == event->object)
1141 zbx_vector_uint64_append(&objectids, event->objectid);
1142 }
1143
1144 if (0 != objectids.values_num)
1145 {
1146 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1147 "select dserviceid"
1148 " from dservices"
1149 "%s dcheckid=" ZBX_FS_UI64
1150 " and",
1151 operation_where,
1152 condition_value);
1153
1154 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1155 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1156 objectids.values_num);
1157
1158 result = DBselect("%s", sql);
1159
1160 while (NULL != (row = DBfetch(result)))
1161 {
1162 zbx_uint64_t objectid;
1163
1164 ZBX_STR2UINT64(objectid, row[0]);
1165 add_condition_match(esc_events, condition, objectid, object);
1166 }
1167 DBfree_result(result);
1168 }
1169
1170 zbx_vector_uint64_destroy(&objectids);
1171 zbx_free(sql);
1172
1173 return SUCCEED;
1174 }
1175
1176 /******************************************************************************
1177 * *
1178 * Function: check_dobject_condition *
1179 * *
1180 * Purpose: check discovery object condition *
1181 * *
1182 * Parameters: esc_events - [IN] events to check *
1183 * condition - [IN/OUT] condition for matching, outputs *
1184 * event ids that match condition *
1185 * *
1186 * Return value: SUCCEED - supported operator *
1187 * NOTSUPPORTED - not supported operator *
1188 * *
1189 ******************************************************************************/
check_dobject_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1190 static int check_dobject_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1191 {
1192 int i, condition_value_i = atoi(condition->value);
1193
1194 if (CONDITION_OPERATOR_EQUAL != condition->op)
1195 return NOTSUPPORTED;
1196
1197 for (i = 0; i < esc_events->values_num; i++)
1198 {
1199 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1200
1201 if (event->object == condition_value_i)
1202 zbx_vector_uint64_append(&condition->eventids, event->eventid);
1203 }
1204
1205 return SUCCEED;
1206 }
1207
1208 /******************************************************************************
1209 * *
1210 * Function: check_proxy_condition *
1211 * *
1212 * Purpose: check proxy condition for discovery event *
1213 * *
1214 * Parameters: esc_events - [IN] events to check *
1215 * condition - [IN/OUT] condition for matching, outputs *
1216 * event ids that match condition *
1217 * *
1218 * Return value: SUCCEED - supported operator *
1219 * NOTSUPPORTED - not supported operator *
1220 * *
1221 ******************************************************************************/
check_proxy_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1222 static int check_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1223 {
1224 char *sql = NULL, *operation_and;
1225 size_t sql_alloc = 0, i;
1226 DB_RESULT result;
1227 DB_ROW row;
1228 int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1229 zbx_vector_uint64_t objectids[2];
1230 zbx_uint64_t condition_value;
1231
1232 if (CONDITION_OPERATOR_EQUAL == condition->op)
1233 operation_and = " and";
1234 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1235 operation_and = " and not";
1236 else
1237 return NOTSUPPORTED;
1238
1239 ZBX_STR2UINT64(condition_value, condition->value);
1240
1241 zbx_vector_uint64_create(&objectids[0]);
1242 zbx_vector_uint64_create(&objectids[1]);
1243
1244 get_object_ids_discovery(esc_events, objectids);
1245
1246 for (i = 0; i < (int)ARRSIZE(objects); i++)
1247 {
1248 size_t sql_offset = 0;
1249
1250 if (0 == objectids[i].values_num)
1251 continue;
1252
1253 if (EVENT_OBJECT_DHOST == objects[i])
1254 {
1255 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1256 "select h.dhostid"
1257 " from drules r,dhosts h"
1258 " where r.druleid=h.druleid"
1259 "%s r.proxy_hostid=" ZBX_FS_UI64
1260 " and",
1261 operation_and,
1262 condition_value);
1263
1264 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "h.dhostid", objectids[i].values,
1265 objectids[i].values_num);
1266 }
1267 else /* EVENT_OBJECT_DSERVICE */
1268 {
1269 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1270 "select s.dserviceid"
1271 " from drules r,dhosts h,dservices s"
1272 " where r.druleid=h.druleid"
1273 " and h.dhostid=s.dhostid"
1274 "%s r.proxy_hostid=" ZBX_FS_UI64
1275 " and",
1276 operation_and,
1277 condition_value);
1278
1279 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.dserviceid",
1280 objectids[i].values, objectids[i].values_num);
1281 }
1282
1283 result = DBselect("%s", sql);
1284
1285 while (NULL != (row = DBfetch(result)))
1286 {
1287 zbx_uint64_t objectid;
1288
1289 ZBX_STR2UINT64(objectid, row[0]);
1290 add_condition_match(esc_events, condition, objectid, objects[i]);
1291 }
1292 DBfree_result(result);
1293 }
1294
1295 zbx_vector_uint64_destroy(&objectids[0]);
1296 zbx_vector_uint64_destroy(&objectids[1]);
1297 zbx_free(sql);
1298
1299 return SUCCEED;
1300 }
1301
1302 /******************************************************************************
1303 * *
1304 * Function: check_dvalue_condition *
1305 * *
1306 * Purpose: check discovery value condition *
1307 * *
1308 * Parameters: esc_events - [IN] events to check *
1309 * condition - [IN/OUT] condition for matching, outputs *
1310 * event ids that match condition *
1311 * *
1312 * Return value: SUCCEED - supported operator *
1313 * NOTSUPPORTED - not supported operator *
1314 * *
1315 ******************************************************************************/
check_dvalue_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1316 static int check_dvalue_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1317 {
1318 char *sql = NULL;
1319 size_t sql_alloc = 0, sql_offset = 0;
1320 DB_RESULT result;
1321 DB_ROW row;
1322 int object = EVENT_OBJECT_DSERVICE;
1323 zbx_vector_uint64_t objectids;
1324 int i;
1325
1326 switch (condition->op)
1327 {
1328 case CONDITION_OPERATOR_EQUAL:
1329 case CONDITION_OPERATOR_NOT_EQUAL:
1330 case CONDITION_OPERATOR_MORE_EQUAL:
1331 case CONDITION_OPERATOR_LESS_EQUAL:
1332 case CONDITION_OPERATOR_LIKE:
1333 case CONDITION_OPERATOR_NOT_LIKE:
1334 break;
1335 default:
1336 return NOTSUPPORTED;
1337 }
1338
1339 zbx_vector_uint64_create(&objectids);
1340
1341 for (i = 0; i < esc_events->values_num; i++)
1342 {
1343 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1344
1345 if (object == event->object)
1346 zbx_vector_uint64_append(&objectids, event->objectid);
1347 }
1348
1349 if (0 != objectids.values_num)
1350 {
1351 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1352 "select dserviceid,value"
1353 " from dservices"
1354 " where");
1355
1356 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1357 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1358 objectids.values_num);
1359
1360 result = DBselect("%s", sql);
1361
1362 while (NULL != (row = DBfetch(result)))
1363 {
1364 zbx_uint64_t objectid;
1365
1366 ZBX_STR2UINT64(objectid, row[0]);
1367
1368 switch (condition->op)
1369 {
1370 case CONDITION_OPERATOR_EQUAL:
1371 if (0 == strcmp(condition->value, row[1]))
1372 add_condition_match(esc_events, condition, objectid, object);
1373 break;
1374 case CONDITION_OPERATOR_NOT_EQUAL:
1375 if (0 != strcmp(condition->value, row[1]))
1376 add_condition_match(esc_events, condition, objectid, object);
1377 break;
1378 case CONDITION_OPERATOR_MORE_EQUAL:
1379 if (0 <= strcmp(row[1], condition->value))
1380 add_condition_match(esc_events, condition, objectid, object);
1381 break;
1382 case CONDITION_OPERATOR_LESS_EQUAL:
1383 if (0 >= strcmp(row[1], condition->value))
1384 add_condition_match(esc_events, condition, objectid, object);
1385 break;
1386 case CONDITION_OPERATOR_LIKE:
1387 if (NULL != strstr(row[1], condition->value))
1388 add_condition_match(esc_events, condition, objectid, object);
1389 break;
1390 case CONDITION_OPERATOR_NOT_LIKE:
1391 if (NULL == strstr(row[1], condition->value))
1392 add_condition_match(esc_events, condition, objectid, object);
1393 break;
1394 }
1395 }
1396 DBfree_result(result);
1397 }
1398
1399 zbx_vector_uint64_destroy(&objectids);
1400 zbx_free(sql);
1401
1402 return SUCCEED;
1403 }
1404
1405 /******************************************************************************
1406 * *
1407 * Function: check_dhost_ip_condition *
1408 * *
1409 * Purpose: check host ip condition for discovery event *
1410 * *
1411 * Parameters: esc_events - [IN] events to check *
1412 * condition - [IN/OUT] condition for matching, outputs *
1413 * event ids that match condition *
1414 * *
1415 * Return value: SUCCEED - supported operator *
1416 * NOTSUPPORTED - not supported operator *
1417 * *
1418 ******************************************************************************/
check_dhost_ip_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1419 static int check_dhost_ip_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1420 {
1421 char *sql = NULL;
1422 size_t sql_alloc = 0, i;
1423 DB_RESULT result;
1424 DB_ROW row;
1425 int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1426 zbx_vector_uint64_t objectids[2];
1427 zbx_uint64_t condition_value;
1428
1429 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1430 return NOTSUPPORTED;
1431
1432 ZBX_STR2UINT64(condition_value, condition->value);
1433
1434 zbx_vector_uint64_create(&objectids[0]);
1435 zbx_vector_uint64_create(&objectids[1]);
1436
1437 get_object_ids_discovery(esc_events, objectids);
1438
1439 for (i = 0; i < (int)ARRSIZE(objects); i++)
1440 {
1441 size_t sql_offset = 0;
1442
1443 if (0 == objectids[i].values_num)
1444 continue;
1445
1446 if (EVENT_OBJECT_DHOST == objects[i])
1447 {
1448 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1449 "select distinct dhostid,ip"
1450 " from dservices"
1451 " where");
1452
1453 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid", objectids[i].values,
1454 objectids[i].values_num);
1455 }
1456 else /* EVENT_OBJECT_DSERVICE */
1457 {
1458 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1459 "select distinct dserviceid,ip"
1460 " from dservices"
1461 " where");
1462
1463 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid",
1464 objectids[i].values, objectids[i].values_num);
1465 }
1466
1467 result = DBselect("%s", sql);
1468
1469 while (NULL != (row = DBfetch(result)))
1470 {
1471 zbx_uint64_t objectid;
1472
1473 ZBX_STR2UINT64(objectid, row[0]);
1474 switch (condition->op)
1475 {
1476 case CONDITION_OPERATOR_EQUAL:
1477 if (SUCCEED == ip_in_list(condition->value, row[1]))
1478 add_condition_match(esc_events, condition, objectid, objects[i]);
1479 break;
1480 case CONDITION_OPERATOR_NOT_EQUAL:
1481 if (SUCCEED != ip_in_list(condition->value, row[1]))
1482 add_condition_match(esc_events, condition, objectid, objects[i]);
1483 break;
1484 }
1485 }
1486 DBfree_result(result);
1487 }
1488
1489 zbx_vector_uint64_destroy(&objectids[0]);
1490 zbx_vector_uint64_destroy(&objectids[1]);
1491 zbx_free(sql);
1492
1493 return SUCCEED;
1494 }
1495
1496 /******************************************************************************
1497 * *
1498 * Function: check_dservice_type_condition *
1499 * *
1500 * Purpose: check service type condition for discovery event *
1501 * *
1502 * Parameters: esc_events - [IN] events to check *
1503 * condition - [IN/OUT] condition for matching, outputs *
1504 * event ids that match condition *
1505 * *
1506 * Return value: SUCCEED - supported operator *
1507 * NOTSUPPORTED - not supported operator *
1508 * *
1509 ******************************************************************************/
check_dservice_type_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1510 static int check_dservice_type_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1511 {
1512 char *sql = NULL;
1513 size_t sql_alloc = 0, sql_offset = 0;
1514 DB_RESULT result;
1515 DB_ROW row;
1516 int object = EVENT_OBJECT_DSERVICE;
1517 zbx_vector_uint64_t objectids;
1518 int i, condition_value_i;
1519
1520 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1521 return NOTSUPPORTED;
1522
1523 condition_value_i = atoi(condition->value);
1524
1525 zbx_vector_uint64_create(&objectids);
1526
1527 for (i = 0; i < esc_events->values_num; i++)
1528 {
1529 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1530
1531 if (object == event->object)
1532 zbx_vector_uint64_append(&objectids, event->objectid);
1533 }
1534
1535 if (0 != objectids.values_num)
1536 {
1537 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1538 "select ds.dserviceid,dc.type"
1539 " from dservices ds,dchecks dc"
1540 " where ds.dcheckid=dc.dcheckid"
1541 " and");
1542
1543 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1544 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ds.dserviceid", objectids.values,
1545 objectids.values_num);
1546
1547 result = DBselect("%s", sql);
1548
1549 while (NULL != (row = DBfetch(result)))
1550 {
1551 zbx_uint64_t objectid;
1552 int tmp_int;
1553
1554 ZBX_STR2UINT64(objectid, row[0]);
1555 tmp_int = atoi(row[1]);
1556
1557 switch (condition->op)
1558 {
1559 case CONDITION_OPERATOR_EQUAL:
1560 if (condition_value_i == tmp_int)
1561 add_condition_match(esc_events, condition, objectid, object);
1562 break;
1563 case CONDITION_OPERATOR_NOT_EQUAL:
1564 if (condition_value_i != tmp_int)
1565 add_condition_match(esc_events, condition, objectid, object);
1566 break;
1567 }
1568 }
1569 DBfree_result(result);
1570 }
1571
1572 zbx_vector_uint64_destroy(&objectids);
1573 zbx_free(sql);
1574
1575 return SUCCEED;
1576 }
1577
1578 /******************************************************************************
1579 * *
1580 * Function: check_dstatus_condition *
1581 * *
1582 * Purpose: check discovery status condition *
1583 * *
1584 * Parameters: esc_events - [IN] events to check *
1585 * condition - [IN/OUT] condition for matching, outputs *
1586 * event ids that match condition *
1587 * *
1588 * Return value: SUCCEED - supported operator *
1589 * NOTSUPPORTED - not supported operator *
1590 * *
1591 ******************************************************************************/
check_dstatus_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1592 static int check_dstatus_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1593 {
1594 int i, condition_value_i = atoi(condition->value);
1595
1596 for (i = 0; i < esc_events->values_num; i++)
1597 {
1598 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1599
1600 switch (condition->op)
1601 {
1602 case CONDITION_OPERATOR_EQUAL:
1603 if (condition_value_i == event->value)
1604 zbx_vector_uint64_append(&condition->eventids, event->eventid);
1605 break;
1606 case CONDITION_OPERATOR_NOT_EQUAL:
1607 if (condition_value_i != event->value)
1608 zbx_vector_uint64_append(&condition->eventids, event->eventid);
1609 break;
1610 default:
1611 return NOTSUPPORTED;
1612 }
1613 }
1614
1615 return SUCCEED;
1616 }
1617
1618 /******************************************************************************
1619 * *
1620 * Function: check_duptime_condition *
1621 * *
1622 * Purpose: check uptime condition for discovery *
1623 * *
1624 * Parameters: esc_events - [IN] events to check *
1625 * condition - [IN/OUT] condition for matching, outputs *
1626 * event ids that match condition *
1627 * *
1628 * Return value: SUCCEED - supported operator *
1629 * NOTSUPPORTED - not supported operator *
1630 * *
1631 ******************************************************************************/
check_duptime_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1632 static int check_duptime_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1633 {
1634 char *sql = NULL;
1635 size_t sql_alloc = 0, i;
1636 DB_RESULT result;
1637 DB_ROW row;
1638 int objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1639 zbx_vector_uint64_t objectids[2];
1640 int condition_value_i;
1641
1642 if (CONDITION_OPERATOR_LESS_EQUAL != condition->op && CONDITION_OPERATOR_MORE_EQUAL != condition->op)
1643 return NOTSUPPORTED;
1644
1645 condition_value_i = atoi(condition->value);
1646
1647 zbx_vector_uint64_create(&objectids[0]);
1648 zbx_vector_uint64_create(&objectids[1]);
1649
1650 get_object_ids_discovery(esc_events, objectids);
1651
1652 for (i = 0; i < (int)ARRSIZE(objects); i++)
1653 {
1654 size_t sql_offset = 0;
1655
1656 if (0 == objectids[i].values_num)
1657 continue;
1658
1659 if (EVENT_OBJECT_DHOST == objects[i])
1660 {
1661 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1662 "select dhostid,status,lastup,lastdown"
1663 " from dhosts"
1664 " where");
1665
1666 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid",
1667 objectids[i].values, objectids[i].values_num);
1668 }
1669 else /* EVENT_OBJECT_DSERVICE */
1670 {
1671 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1672 "select dserviceid,status,lastup,lastdown"
1673 " from dservices"
1674 " where");
1675
1676 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid",
1677 objectids[i].values, objectids[i].values_num);
1678 }
1679
1680 result = DBselect("%s", sql);
1681
1682 while (NULL != (row = DBfetch(result)))
1683 {
1684 zbx_uint64_t objectid;
1685 int now, tmp_int;
1686
1687 ZBX_STR2UINT64(objectid, row[0]);
1688
1689 now = time(NULL);
1690 tmp_int = DOBJECT_STATUS_UP == atoi(row[1]) ? atoi(row[2]) : atoi(row[3]);
1691
1692 switch (condition->op)
1693 {
1694 case CONDITION_OPERATOR_LESS_EQUAL:
1695 if (0 != tmp_int && (now - tmp_int) <= condition_value_i)
1696 add_condition_match(esc_events, condition, objectid, objects[i]);
1697 break;
1698 case CONDITION_OPERATOR_MORE_EQUAL:
1699 if (0 != tmp_int && (now - tmp_int) >= condition_value_i)
1700 add_condition_match(esc_events, condition, objectid, objects[i]);
1701 break;
1702 }
1703 }
1704 DBfree_result(result);
1705 }
1706
1707 zbx_vector_uint64_destroy(&objectids[0]);
1708 zbx_vector_uint64_destroy(&objectids[1]);
1709 zbx_free(sql);
1710
1711 return SUCCEED;
1712 }
1713
1714 /******************************************************************************
1715 * *
1716 * Function: check_dservice_port_condition *
1717 * *
1718 * Purpose: check service port condition for discovery *
1719 * *
1720 * Parameters: esc_events - [IN] events to check *
1721 * condition - [IN/OUT] condition for matching, outputs *
1722 * event ids that match condition *
1723 * *
1724 * Return value: SUCCEED - supported operator *
1725 * NOTSUPPORTED - not supported operator *
1726 * *
1727 ******************************************************************************/
check_dservice_port_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1728 static int check_dservice_port_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1729 {
1730 char *sql = NULL;
1731 size_t sql_alloc = 0, sql_offset = 0;
1732 DB_RESULT result;
1733 DB_ROW row;
1734 int object = EVENT_OBJECT_DSERVICE;
1735 zbx_vector_uint64_t objectids;
1736 int i;
1737
1738 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1739 return NOTSUPPORTED;
1740
1741 zbx_vector_uint64_create(&objectids);
1742
1743 for (i = 0; i < esc_events->values_num; i++)
1744 {
1745 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
1746
1747 if (object == event->object)
1748 zbx_vector_uint64_append(&objectids, event->objectid);
1749 }
1750
1751 if (0 != objectids.values_num)
1752 {
1753 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1754 "select dserviceid,port"
1755 " from dservices"
1756 " where");
1757
1758 zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1759 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1760 objectids.values_num);
1761
1762 result = DBselect("%s", sql);
1763
1764 while (NULL != (row = DBfetch(result)))
1765 {
1766 zbx_uint64_t objectid;
1767
1768 ZBX_STR2UINT64(objectid, row[0]);
1769 switch (condition->op)
1770 {
1771 case CONDITION_OPERATOR_EQUAL:
1772 if (SUCCEED == int_in_list(condition->value, atoi(row[1])))
1773 add_condition_match(esc_events, condition, objectid, object);
1774 break;
1775 case CONDITION_OPERATOR_NOT_EQUAL:
1776 if (SUCCEED != int_in_list(condition->value, atoi(row[1])))
1777 add_condition_match(esc_events, condition, objectid, object);
1778 break;
1779 }
1780 }
1781 DBfree_result(result);
1782 }
1783
1784 zbx_vector_uint64_destroy(&objectids);
1785 zbx_free(sql);
1786
1787 return SUCCEED;
1788 }
1789
1790 /******************************************************************************
1791 * *
1792 * Function: check_discovery_condition *
1793 * *
1794 * Purpose: check if event matches single condition *
1795 * *
1796 * Parameters: event - discovery event to check *
1797 * (event->source == EVENT_SOURCE_DISCOVERY) *
1798 * condition - condition for matching *
1799 * *
1800 * Return value: SUCCEED - matches, FAIL - otherwise *
1801 * *
1802 * Author: Alexei Vladishev *
1803 * *
1804 ******************************************************************************/
check_discovery_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1805 static void check_discovery_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1806 {
1807 int ret;
1808
1809 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1810
1811 switch (condition->conditiontype)
1812 {
1813 case CONDITION_TYPE_DRULE:
1814 ret = check_drule_condition(esc_events, condition);
1815 break;
1816 case CONDITION_TYPE_DCHECK:
1817 ret = check_dcheck_condition(esc_events, condition);
1818 break;
1819 case CONDITION_TYPE_DOBJECT:
1820 ret = check_dobject_condition(esc_events, condition);
1821 break;
1822 case CONDITION_TYPE_PROXY:
1823 ret = check_proxy_condition(esc_events, condition);
1824 break;
1825 case CONDITION_TYPE_DVALUE:
1826 ret = check_dvalue_condition(esc_events, condition);
1827 break;
1828 case CONDITION_TYPE_DHOST_IP:
1829 ret = check_dhost_ip_condition(esc_events, condition);
1830 break;
1831 case CONDITION_TYPE_DSERVICE_TYPE:
1832 ret = check_dservice_type_condition(esc_events, condition);
1833 break;
1834 case CONDITION_TYPE_DSTATUS:
1835 ret = check_dstatus_condition(esc_events, condition);
1836 break;
1837 case CONDITION_TYPE_DUPTIME:
1838 ret = check_duptime_condition(esc_events, condition);
1839 break;
1840 case CONDITION_TYPE_DSERVICE_PORT:
1841 ret = check_dservice_port_condition(esc_events, condition);
1842 break;
1843 default:
1844 ret = FAIL;
1845 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
1846 (int)condition->conditiontype, condition->conditionid);
1847 }
1848
1849 if (NOTSUPPORTED == ret)
1850 {
1851 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
1852 (int)condition->op, condition->conditionid);
1853 }
1854
1855 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
1856 }
1857
1858 /******************************************************************************
1859 * *
1860 * Function: check_hostname_metadata_condition *
1861 * *
1862 * Purpose: check metadata or host condition for auto registration *
1863 * *
1864 * Parameters: esc_events - [IN] events to check *
1865 * condition - [IN/OUT] condition for matching, outputs *
1866 * event ids that match condition *
1867 * *
1868 * Return value: SUCCEED - supported operator *
1869 * NOTSUPPORTED - not supported operator *
1870 * *
1871 ******************************************************************************/
check_hostname_metadata_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1872 static int check_hostname_metadata_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1873 {
1874 char *sql = NULL;
1875 size_t sql_alloc = 0, sql_offset = 0;
1876 DB_RESULT result;
1877 DB_ROW row;
1878 int object = EVENT_OBJECT_ZABBIX_ACTIVE;
1879 zbx_vector_uint64_t objectids;
1880 const char *condition_field;
1881
1882 switch(condition->op)
1883 {
1884 case CONDITION_OPERATOR_LIKE:
1885 case CONDITION_OPERATOR_NOT_LIKE:
1886 case CONDITION_OPERATOR_REGEXP:
1887 case CONDITION_OPERATOR_NOT_REGEXP:
1888 break;
1889 default:
1890 return NOTSUPPORTED;
1891 }
1892
1893 if (CONDITION_TYPE_HOST_NAME == condition->conditiontype)
1894 condition_field = "host";
1895 else
1896 condition_field = "host_metadata";
1897
1898 zbx_vector_uint64_create(&objectids);
1899 get_object_ids(esc_events, &objectids);
1900
1901 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1902 "select autoreg_hostid,%s"
1903 " from autoreg_host"
1904 " where",
1905 condition_field);
1906
1907 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "autoreg_hostid", objectids.values, objectids.values_num);
1908
1909 result = DBselect("%s", sql);
1910
1911 while (NULL != (row = DBfetch(result)))
1912 {
1913 zbx_uint64_t objectid;
1914
1915 ZBX_STR2UINT64(objectid, row[0]);
1916
1917 switch (condition->op)
1918 {
1919 case CONDITION_OPERATOR_LIKE:
1920 if (NULL != strstr(row[1], condition->value))
1921 add_condition_match(esc_events, condition, objectid, object);
1922 break;
1923 case CONDITION_OPERATOR_NOT_LIKE:
1924 if (NULL == strstr(row[1], condition->value))
1925 add_condition_match(esc_events, condition, objectid, object);
1926 break;
1927 case CONDITION_OPERATOR_REGEXP:
1928 if (NULL != zbx_regexp_match(row[1], condition->value, NULL))
1929 add_condition_match(esc_events, condition, objectid, object);
1930 break;
1931 case CONDITION_OPERATOR_NOT_REGEXP:
1932 if (NULL == zbx_regexp_match(row[1], condition->value, NULL))
1933 add_condition_match(esc_events, condition, objectid, object);
1934 break;
1935 }
1936 }
1937 DBfree_result(result);
1938
1939 zbx_vector_uint64_destroy(&objectids);
1940 zbx_free(sql);
1941
1942 return SUCCEED;
1943 }
1944
1945 /******************************************************************************
1946 * *
1947 * Function: check_areg_proxy_condition *
1948 * *
1949 * Purpose: check proxy condition for auto registration *
1950 * *
1951 * Parameters: esc_events - [IN] events to check *
1952 * condition - [IN/OUT] condition for matching, outputs *
1953 * event ids that match condition *
1954 * *
1955 * Return value: SUCCEED - supported operator *
1956 * NOTSUPPORTED - not supported operator *
1957 * *
1958 ******************************************************************************/
check_areg_proxy_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1959 static int check_areg_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1960 {
1961 char *sql = NULL;
1962 size_t sql_alloc = 0, sql_offset = 0;
1963 DB_RESULT result;
1964 DB_ROW row;
1965 int object = EVENT_OBJECT_ZABBIX_ACTIVE;
1966 zbx_vector_uint64_t objectids;
1967 zbx_uint64_t condition_value;
1968
1969 ZBX_STR2UINT64(condition_value, condition->value);
1970
1971 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1972 return NOTSUPPORTED;
1973
1974 zbx_vector_uint64_create(&objectids);
1975 get_object_ids(esc_events, &objectids);
1976
1977 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1978 "select autoreg_hostid,proxy_hostid"
1979 " from autoreg_host"
1980 " where");
1981
1982 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "autoreg_hostid",
1983 objectids.values, objectids.values_num);
1984
1985 result = DBselect("%s", sql);
1986
1987 while (NULL != (row = DBfetch(result)))
1988 {
1989 zbx_uint64_t id;
1990 zbx_uint64_t objectid;
1991
1992 ZBX_STR2UINT64(objectid, row[0]);
1993 ZBX_DBROW2UINT64(id, row[1]);
1994
1995 switch (condition->op)
1996 {
1997 case CONDITION_OPERATOR_EQUAL:
1998 if (id == condition_value)
1999 add_condition_match(esc_events, condition, objectid, object);
2000 break;
2001 case CONDITION_OPERATOR_NOT_EQUAL:
2002 if (id != condition_value)
2003 add_condition_match(esc_events, condition, objectid, object);
2004 break;
2005 }
2006 }
2007 DBfree_result(result);
2008
2009 zbx_vector_uint64_destroy(&objectids);
2010 zbx_free(sql);
2011
2012 return SUCCEED;
2013 }
2014
2015 /******************************************************************************
2016 * *
2017 * Function: check_autoregistration_condition *
2018 * *
2019 * Purpose: check if event matches single condition *
2020 * *
2021 * Parameters: event - autoregistration event to check *
2022 * (event->source == EVENT_SOURCE_AUTOREGISTRATION) *
2023 * condition - condition for matching *
2024 * *
2025 * Return value: SUCCEED - matches, FAIL - otherwise *
2026 * *
2027 * Author: Alexei Vladishev *
2028 * *
2029 ******************************************************************************/
check_autoregistration_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2030 static void check_autoregistration_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2031 {
2032 const char *__function_name = "check_auto_registration_condition";
2033 int ret;
2034
2035 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2036
2037 switch (condition->conditiontype)
2038 {
2039 case CONDITION_TYPE_HOST_NAME:
2040 case CONDITION_TYPE_HOST_METADATA:
2041 ret = check_hostname_metadata_condition(esc_events, condition);
2042 break;
2043 case CONDITION_TYPE_PROXY:
2044 ret = check_areg_proxy_condition(esc_events, condition);
2045 break;
2046 default:
2047 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
2048 (int)condition->conditiontype, condition->conditionid);
2049 ret = FAIL;
2050 }
2051
2052 if (NOTSUPPORTED == ret)
2053 {
2054 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
2055 (int)condition->op, condition->conditionid);
2056 }
2057
2058 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2059 }
2060
2061 /******************************************************************************
2062 * *
2063 * Function: is_supported_event_object *
2064 * *
2065 * Purpose: not all event objects are supported for internal events *
2066 * *
2067 * Parameters: events - [IN] events to check *
2068 * *
2069 * Return value: SUCCEED - supported *
2070 * FAIL - not supported *
2071 * *
2072 ******************************************************************************/
is_supported_event_object(const DB_EVENT * event)2073 static int is_supported_event_object(const DB_EVENT *event)
2074 {
2075 return (EVENT_OBJECT_TRIGGER == event->object || EVENT_OBJECT_ITEM == event->object ||
2076 EVENT_OBJECT_LLDRULE == event->object) ? SUCCEED : FAIL;
2077 }
2078
2079 /******************************************************************************
2080 * *
2081 * Function: check_intern_event_type_condition *
2082 * *
2083 * Purpose: check event type condition for internal events *
2084 * *
2085 * Parameters: esc_events - [IN] events to check *
2086 * condition - [IN/OUT] condition for matching, outputs *
2087 * event ids that match condition *
2088 * *
2089 * Return value: SUCCEED - supported operator *
2090 * NOTSUPPORTED - not supported operator *
2091 * *
2092 ******************************************************************************/
check_intern_event_type_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2093 static int check_intern_event_type_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2094 {
2095 int i;
2096 zbx_uint64_t condition_value;
2097
2098 condition_value = atoi(condition->value);
2099
2100 for (i = 0; i < esc_events->values_num; i++)
2101 {
2102 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
2103
2104 if (FAIL == is_supported_event_object(event))
2105 {
2106 zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d] for condition id [" ZBX_FS_UI64 "]",
2107 event->object, condition->conditionid);
2108 continue;
2109 }
2110
2111 switch (condition_value)
2112 {
2113 case EVENT_TYPE_ITEM_NOTSUPPORTED:
2114 if (EVENT_OBJECT_ITEM == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
2115 zbx_vector_uint64_append(&condition->eventids, event->eventid);
2116 break;
2117 case EVENT_TYPE_TRIGGER_UNKNOWN:
2118 if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_STATE_UNKNOWN == event->value)
2119 zbx_vector_uint64_append(&condition->eventids, event->eventid);
2120 break;
2121 case EVENT_TYPE_LLDRULE_NOTSUPPORTED:
2122 if (EVENT_OBJECT_LLDRULE == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
2123 zbx_vector_uint64_append(&condition->eventids, event->eventid);
2124 break;
2125 default:
2126 return NOTSUPPORTED;
2127 }
2128 }
2129
2130 return SUCCEED;
2131 }
2132
2133 /******************************************************************************
2134 * *
2135 * Function: get_object_ids_internal *
2136 * *
2137 * Purpose: get objectids of escalation internal events *
2138 * *
2139 * Parameters: esc_events - [IN] events to check *
2140 * objectids - [OUT] event objectids to be used in condition *
2141 * allocation 2 vectors where first one is *
2142 * trigger object ids, second is rest *
2143 * objects - [IN] the array of event objects *
2144 * objects_num - [IN] the number of objects in objects array *
2145 * *
2146 ******************************************************************************/
get_object_ids_internal(const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids,const int * objects,const int objects_num)2147 static void get_object_ids_internal(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids,
2148 const int *objects, const int objects_num)
2149 {
2150 int i, j;
2151
2152 for (i = 0; i < esc_events->values_num; i++)
2153 {
2154 const DB_EVENT *event = (DB_EVENT *)esc_events->values[i];
2155
2156 for (j = 0; j < objects_num; j++)
2157 {
2158 if (event->object == objects[j])
2159 {
2160 zbx_vector_uint64_append(&objectids[j], event->objectid);
2161 break;
2162 }
2163 }
2164
2165 if (j == objects_num)
2166 zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d]", event->object);
2167 }
2168
2169 for (i = 0; i < objects_num; i++)
2170 zbx_vector_uint64_uniq(&objectids[i], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2171 }
2172
2173 /******************************************************************************
2174 * *
2175 * Function: check_intern_host_group_condition *
2176 * *
2177 * Purpose: check host group condition for internal events *
2178 * *
2179 * Parameters: esc_events - [IN] events to check *
2180 * condition - [IN/OUT] condition for matching, outputs *
2181 * event ids that match condition *
2182 * *
2183 * Return value: SUCCEED - supported operator *
2184 * NOTSUPPORTED - not supported operator *
2185 * *
2186 ******************************************************************************/
check_intern_host_group_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2187 static int check_intern_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2188 {
2189 char *sql = NULL;
2190 size_t sql_alloc = 0, i;
2191 DB_RESULT result;
2192 DB_ROW row;
2193 int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2194 zbx_vector_uint64_t objectids[3], groupids;
2195 zbx_uint64_t condition_value;
2196
2197 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
2198 return NOTSUPPORTED;
2199
2200 ZBX_STR2UINT64(condition_value, condition->value);
2201
2202 for (i = 0; i < (int)ARRSIZE(objects); i++)
2203 zbx_vector_uint64_create(&objectids[i]);
2204
2205 zbx_vector_uint64_create(&groupids);
2206
2207 get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2208
2209 zbx_dc_get_nested_hostgroupids(&condition_value, 1, &groupids);
2210
2211 for (i = 0; i < (int)ARRSIZE(objects); i++)
2212 {
2213 size_t sql_offset = 0;
2214
2215 if (0 == objectids[i].values_num)
2216 continue;
2217
2218 if (EVENT_OBJECT_TRIGGER == objects[i])
2219 {
2220 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2221 "select distinct f.triggerid"
2222 " from hosts_groups hg,hosts h,items i,functions f"
2223 " where hg.hostid=h.hostid"
2224 " and h.hostid=i.hostid"
2225 " and i.itemid=f.itemid"
2226 " and");
2227
2228 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", objectids[i].values,
2229 objectids[i].values_num);
2230 }
2231 else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2232 {
2233 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2234 "select distinct i.itemid"
2235 " from hosts_groups hg,hosts h,items i"
2236 " where hg.hostid=h.hostid"
2237 " and h.hostid=i.hostid"
2238 " and");
2239
2240 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid",
2241 objectids[i].values, objectids[i].values_num);
2242 }
2243
2244 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and");
2245 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.groupid", groupids.values,
2246 groupids.values_num);
2247
2248 result = DBselect("%s", sql);
2249
2250 while (NULL != (row = DBfetch(result)))
2251 {
2252 zbx_uint64_t objectid;
2253
2254 ZBX_STR2UINT64(objectid, row[0]);
2255 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2256 {
2257 int index;
2258
2259 if (FAIL != (index = zbx_vector_uint64_search(&objectids[i], objectid,
2260 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2261 {
2262 zbx_vector_uint64_remove_noorder(&objectids[i], index);
2263 }
2264 }
2265 else
2266 add_condition_match(esc_events, condition, objectid, objects[i]);
2267 }
2268 DBfree_result(result);
2269 }
2270
2271 for (i = 0; i < (int)ARRSIZE(objects); i++)
2272 {
2273 if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2274 {
2275 int j;
2276
2277 for (j = 0; j < objectids[i].values_num; j++)
2278 add_condition_match(esc_events, condition, objectids[i].values[j], objects[i]);
2279 }
2280
2281 zbx_vector_uint64_destroy(&objectids[i]);
2282 }
2283
2284 zbx_vector_uint64_destroy(&groupids);
2285 zbx_free(sql);
2286
2287 return SUCCEED;
2288 }
2289
2290 /******************************************************************************
2291 * *
2292 * Function: item_parents_sql_alloc *
2293 * *
2294 * Purpose: get parent id from item discovery *
2295 * *
2296 * Parameters: sql [IN/OUT] - allocated sql query *
2297 * sql_alloc [IN/OUT] - how much bytes allocated *
2298 * objectids_tmp [IN/OUT] - uses to allocate query, removes *
2299 * duplicates *
2300 * *
2301 ******************************************************************************/
item_parents_sql_alloc(char ** sql,size_t * sql_alloc,zbx_vector_uint64_t * objectids_tmp)2302 static void item_parents_sql_alloc(char **sql, size_t *sql_alloc, zbx_vector_uint64_t *objectids_tmp)
2303 {
2304 size_t sql_offset = 0;
2305
2306 zbx_snprintf_alloc(sql, sql_alloc, &sql_offset,
2307 "select i.itemid,id.parent_itemid"
2308 " from item_discovery id,items i"
2309 " where id.itemid=i.itemid"
2310 " and i.flags=%d"
2311 " and",
2312 ZBX_FLAG_DISCOVERY_CREATED);
2313
2314 DBadd_condition_alloc(sql, sql_alloc, &sql_offset, "i.itemid",
2315 objectids_tmp->values, objectids_tmp->values_num);
2316 }
2317
2318
2319
2320 /******************************************************************************
2321 * *
2322 * Function: check_intern_host_template_condition *
2323 * *
2324 * Purpose: check host template condition for internal events *
2325 * *
2326 * Parameters: esc_events - [IN] events to check *
2327 * condition - [IN/OUT] condition for matching, outputs *
2328 * event ids that match condition *
2329 * *
2330 * Return value: SUCCEED - supported operator *
2331 * NOTSUPPORTED - not supported operator *
2332 * *
2333 ******************************************************************************/
check_intern_host_template_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2334 static int check_intern_host_template_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2335 {
2336 char *sql = NULL;
2337 size_t sql_alloc = 0;
2338 DB_RESULT result;
2339 DB_ROW row;
2340 zbx_uint64_t condition_value;
2341 int i, j;
2342 int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2343 zbx_vector_uint64_t objectids[3];
2344 zbx_vector_uint64_pair_t objectids_pair[3];
2345
2346 if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
2347 return NOTSUPPORTED;
2348
2349 for (i = 0; i < (int)ARRSIZE(objects); i++)
2350 {
2351 zbx_vector_uint64_create(&objectids[i]);
2352 zbx_vector_uint64_pair_create(&objectids_pair[i]);
2353 }
2354
2355 get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2356
2357 ZBX_STR2UINT64(condition_value, condition->value);
2358
2359 for (i = 0; i < (int)ARRSIZE(objects); i++)
2360 {
2361 zbx_vector_uint64_t *objectids_ptr = &objectids[i];
2362 zbx_vector_uint64_pair_t *objectids_pair_ptr = &objectids_pair[i];
2363
2364 if (0 == objectids_ptr->values_num)
2365 continue;
2366
2367 objectids_to_pair(objectids_ptr, objectids_pair_ptr);
2368
2369 if (EVENT_OBJECT_TRIGGER == objects[i])
2370 trigger_parents_sql_alloc(&sql, &sql_alloc, objectids_ptr);
2371 else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2372 item_parents_sql_alloc(&sql, &sql_alloc, objectids_ptr);
2373
2374 result = DBselect("%s", sql);
2375
2376 while (NULL != (row = DBfetch(result)))
2377 {
2378 zbx_uint64_pair_t pair;
2379
2380 ZBX_STR2UINT64(pair.first, row[0]);
2381
2382 if (FAIL != (j = zbx_vector_uint64_pair_search(objectids_pair_ptr, pair,
2383 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2384 {
2385 ZBX_STR2UINT64(objectids_pair_ptr->values[j].second, row[1]);
2386 }
2387 }
2388 DBfree_result(result);
2389
2390 check_object_hierarchy(objects[i], esc_events, objectids_ptr, objectids_pair_ptr, condition, condition_value,
2391 0 == i ?
2392 "select distinct t.triggerid,t.templateid,i.hostid"
2393 " from items i,functions f,triggers t"
2394 " where i.itemid=f.itemid"
2395 " and f.triggerid=t.templateid"
2396 " and" :
2397 "select distinct h.itemid,t.itemid,t.hostid"
2398 " from items t,items h"
2399 " where t.itemid=h.templateid"
2400 " and",
2401 0 == i ? "t.triggerid" : "h.itemid");
2402 }
2403
2404 for (i = 0; i < (int)ARRSIZE(objects); i++)
2405 {
2406 zbx_vector_uint64_destroy(&objectids[i]);
2407 zbx_vector_uint64_pair_destroy(&objectids_pair[i]);
2408 }
2409
2410 zbx_free(sql);
2411
2412 return SUCCEED;
2413 }
2414
2415 /******************************************************************************
2416 * *
2417 * Function: check_intern_host_condition *
2418 * *
2419 * Purpose: check host condition for internal events *
2420 * *
2421 * Parameters: esc_events - [IN] events to check *
2422 * condition - [IN/OUT] condition for matching, outputs *
2423 * event ids that match condition *
2424 * *
2425 * Return value: SUCCEED - supported operator *
2426 * NOTSUPPORTED - not supported operator *
2427 * *
2428 ******************************************************************************/
check_intern_host_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2429 static int check_intern_host_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2430 {
2431 char *sql = NULL, *operation, *operation_item;
2432 size_t sql_alloc = 0, i;
2433 DB_RESULT result;
2434 DB_ROW row;
2435 int objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2436 zbx_vector_uint64_t objectids[3];
2437 zbx_uint64_t condition_value;
2438
2439 if (CONDITION_OPERATOR_EQUAL == condition->op)
2440 {
2441 operation = " and";
2442 operation_item = " where";
2443 }
2444 else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2445 {
2446 operation = " and not";
2447 operation_item = " where not";
2448 }
2449 else
2450 return NOTSUPPORTED;
2451
2452 ZBX_STR2UINT64(condition_value, condition->value);
2453
2454 for (i = 0; i < (int)ARRSIZE(objects); i++)
2455 zbx_vector_uint64_create(&objectids[i]);
2456
2457 get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2458
2459 for (i = 0; i < (int)ARRSIZE(objects); i++)
2460 {
2461 size_t sql_offset = 0;
2462
2463 if (0 == objectids[i].values_num)
2464 continue;
2465
2466 if (EVENT_OBJECT_TRIGGER == objects[i])
2467 {
2468 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2469 "select distinct f.triggerid"
2470 " from items i,functions f"
2471 " where i.itemid=f.itemid"
2472 "%s i.hostid=" ZBX_FS_UI64
2473 " and",
2474 operation,
2475 condition_value);
2476
2477 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid",
2478 objectids[i].values, objectids[i].values_num);
2479 }
2480 else /* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2481 {
2482 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2483 "select itemid"
2484 " from items"
2485 "%s hostid=" ZBX_FS_UI64
2486 " and",
2487 operation_item,
2488 condition_value);
2489
2490 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
2491 objectids[i].values, objectids[i].values_num);
2492 }
2493
2494 result = DBselect("%s", sql);
2495
2496 while (NULL != (row = DBfetch(result)))
2497 {
2498 zbx_uint64_t objectid;
2499
2500 ZBX_STR2UINT64(objectid, row[0]);
2501 add_condition_match(esc_events, condition, objectid, objects[i]);
2502 }
2503 DBfree_result(result);
2504 }
2505
2506 for (i = 0; i < (int)ARRSIZE(objects); i++)
2507 zbx_vector_uint64_destroy(&objectids[i]);
2508
2509 zbx_free(sql);
2510
2511 return SUCCEED;
2512 }
2513
2514 /******************************************************************************
2515 * *
2516 * Function: check_internal_condition *
2517 * *
2518 * Purpose: check if internal event matches single condition *
2519 * *
2520 * Parameters: event - [IN] trigger event to check *
2521 * condition - [IN] condition for matching *
2522 * *
2523 * Return value: SUCCEED - matches, FAIL - otherwise *
2524 * *
2525 ******************************************************************************/
check_internal_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2526 static void check_internal_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2527 {
2528 int ret;
2529
2530 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2531
2532 switch (condition->conditiontype)
2533 {
2534 case CONDITION_TYPE_EVENT_TYPE:
2535 ret = check_intern_event_type_condition(esc_events, condition);
2536 break;
2537 case CONDITION_TYPE_HOST_GROUP:
2538 ret = check_intern_host_group_condition(esc_events, condition);
2539 break;
2540 case CONDITION_TYPE_HOST_TEMPLATE:
2541 ret = check_intern_host_template_condition(esc_events, condition);
2542 break;
2543 case CONDITION_TYPE_HOST:
2544 ret = check_intern_host_condition(esc_events, condition);
2545 break;
2546 case CONDITION_TYPE_EVENT_TAG:
2547 check_condition_event_tag(esc_events, condition);
2548 ret = SUCCEED;
2549 break;
2550 case CONDITION_TYPE_EVENT_TAG_VALUE:
2551 check_condition_event_tag_value(esc_events,condition);
2552 ret = SUCCEED;
2553 break;
2554 default:
2555 ret = FAIL;
2556 zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
2557 (int)condition->conditiontype, condition->conditionid);
2558 }
2559
2560 if (NOTSUPPORTED == ret)
2561 {
2562 zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
2563 (int)condition->op, condition->conditionid);
2564 }
2565
2566
2567 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2568 }
2569
2570 /******************************************************************************
2571 * *
2572 * Function: check_events_condition *
2573 * *
2574 * Purpose: check if multiple events matches single condition *
2575 * *
2576 * Parameters: esc_events - [IN] events to check *
2577 * source - [IN] specific event source that need checking *
2578 * condition - [IN/OUT] condition for matching, outputs *
2579 * event ids that match condition *
2580 * Author: Alexei Vladishev *
2581 * *
2582 ******************************************************************************/
check_events_condition(const zbx_vector_ptr_t * esc_events,unsigned char source,zbx_condition_t * condition)2583 static void check_events_condition(const zbx_vector_ptr_t *esc_events, unsigned char source, zbx_condition_t *condition)
2584 {
2585 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'"
2586 " cond.value2:'%s'", __func__, condition->actionid, condition->conditionid,
2587 condition->value, condition->value2);
2588
2589 switch (source)
2590 {
2591 case EVENT_SOURCE_TRIGGERS:
2592 check_trigger_condition(esc_events, condition);
2593 break;
2594 case EVENT_SOURCE_DISCOVERY:
2595 check_discovery_condition(esc_events, condition);
2596 break;
2597 case EVENT_SOURCE_AUTOREGISTRATION:
2598 check_autoregistration_condition(esc_events, condition);
2599 break;
2600 case EVENT_SOURCE_INTERNAL:
2601 check_internal_condition(esc_events, condition);
2602 break;
2603 default:
2604 zabbix_log(LOG_LEVEL_ERR, "unsupported event source [%d] for condition id [" ZBX_FS_UI64 "]",
2605 source, condition->conditionid);
2606 }
2607
2608 zbx_vector_uint64_sort(&condition->eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2609 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2610 }
2611
2612 /******************************************************************************
2613 * *
2614 * Function: check_action_condition *
2615 * *
2616 * Purpose: check if event matches single condition *
2617 * *
2618 * Parameters: event - event to check *
2619 * condition - condition for matching *
2620 * *
2621 * Return value: SUCCEED - matches, FAIL - otherwise *
2622 * *
2623 * Author: Alexei Vladishev *
2624 * *
2625 ******************************************************************************/
check_action_condition(const DB_EVENT * event,zbx_condition_t * condition)2626 int check_action_condition(const DB_EVENT *event, zbx_condition_t *condition)
2627 {
2628 int ret;
2629 zbx_vector_ptr_t esc_events;
2630
2631 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'"
2632 " cond.value2:'%s'", __func__, condition->actionid, condition->conditionid,
2633 ZBX_NULL2STR(condition->value), ZBX_NULL2STR(condition->value2));
2634
2635 zbx_vector_ptr_create(&esc_events);
2636
2637 zbx_vector_ptr_append(&esc_events, (DB_EVENT *)event);
2638
2639 check_events_condition(&esc_events, event->source, condition);
2640
2641 ret = 0 != condition->eventids.values_num ? SUCCEED : FAIL;
2642
2643 zbx_vector_ptr_destroy(&esc_events);
2644
2645 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2646
2647 return ret;
2648 }
2649
2650 /******************************************************************************
2651 * *
2652 * Function: check_action_conditions *
2653 * *
2654 * Purpose: check if action have to be processed for the event *
2655 * (check all conditions of the action) *
2656 * *
2657 * Parameters: eventid - [IN] the id of event that will be checked *
2658 * action - [IN] action for matching *
2659 * *
2660 * Return value: SUCCEED - matches, FAIL - otherwise *
2661 * *
2662 ******************************************************************************/
check_action_conditions(zbx_uint64_t eventid,const zbx_action_eval_t * action)2663 static int check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t *action)
2664 {
2665 zbx_condition_t *condition;
2666 int condition_result, ret = SUCCEED, id_len, i;
2667 unsigned char old_type = 0xff;
2668 char *expression = NULL, tmp[ZBX_MAX_UINT64_LEN + 2], *ptr, error[256];
2669 double eval_result;
2670
2671 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " eventsource:%d", __func__,
2672 action->actionid, (int)action->eventsource);
2673
2674 if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
2675 expression = zbx_strdup(expression, action->formula);
2676
2677 for (i = 0; i < action->conditions.values_num; i++)
2678 {
2679 condition = (zbx_condition_t *)action->conditions.values[i];
2680
2681 if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype && old_type == condition->conditiontype &&
2682 SUCCEED == ret)
2683 {
2684 continue; /* short-circuit true OR condition block to the next AND condition */
2685 }
2686
2687 condition_result = FAIL == zbx_vector_uint64_bsearch(&condition->eventids, eventid,
2688 ZBX_DEFAULT_UINT64_COMPARE_FUNC) ? FAIL : SUCCEED;
2689
2690 zabbix_log(LOG_LEVEL_DEBUG, " conditionid:" ZBX_FS_UI64 " conditiontype:%d cond.value:'%s' "
2691 "cond.value2:'%s' result:%s", condition->conditionid, (int)condition->conditiontype,
2692 condition->value, condition->value2, zbx_result_string(condition_result));
2693
2694 switch (action->evaltype)
2695 {
2696 case CONDITION_EVAL_TYPE_AND_OR:
2697 if (old_type == condition->conditiontype) /* assume conditions are sorted by type */
2698 {
2699 if (SUCCEED == condition_result)
2700 ret = SUCCEED;
2701 }
2702 else
2703 {
2704 if (FAIL == ret)
2705 goto clean;
2706
2707 ret = condition_result;
2708 old_type = condition->conditiontype;
2709 }
2710
2711 break;
2712 case CONDITION_EVAL_TYPE_AND:
2713 if (FAIL == condition_result) /* break if any AND condition is FALSE */
2714 {
2715 ret = FAIL;
2716 goto clean;
2717 }
2718
2719 break;
2720 case CONDITION_EVAL_TYPE_OR:
2721 if (SUCCEED == condition_result) /* break if any OR condition is TRUE */
2722 {
2723 ret = SUCCEED;
2724 goto clean;
2725 }
2726 ret = FAIL;
2727
2728 break;
2729 case CONDITION_EVAL_TYPE_EXPRESSION:
2730 zbx_snprintf(tmp, sizeof(tmp), "{" ZBX_FS_UI64 "}", condition->conditionid);
2731 id_len = strlen(tmp);
2732
2733 for (ptr = expression; NULL != (ptr = strstr(ptr, tmp)); ptr += id_len)
2734 {
2735 *ptr = (SUCCEED == condition_result ? '1' : '0');
2736 memset(ptr + 1, ' ', id_len - 1);
2737 }
2738
2739 break;
2740 default:
2741 ret = FAIL;
2742 goto clean;
2743 }
2744 }
2745
2746 if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
2747 {
2748 if (SUCCEED == evaluate(&eval_result, expression, error, sizeof(error), NULL))
2749 ret = (SUCCEED != zbx_double_compare(eval_result, 0) ? SUCCEED : FAIL);
2750
2751 zbx_free(expression);
2752 }
2753 clean:
2754 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2755
2756 return ret;
2757 }
2758
2759 /******************************************************************************
2760 * *
2761 * Function: execute_operations *
2762 * *
2763 * Purpose: execute host, group, template operations linked to the action *
2764 * *
2765 * Parameters: action - action to execute operations for *
2766 * *
2767 * Author: Alexei Vladishev *
2768 * *
2769 * Comments: for message, command operations see *
2770 * escalation_execute_operations(), *
2771 * escalation_execute_recovery_operations(). *
2772 * *
2773 ******************************************************************************/
execute_operations(const DB_EVENT * event,zbx_uint64_t actionid)2774 static void execute_operations(const DB_EVENT *event, zbx_uint64_t actionid)
2775 {
2776 DB_RESULT result;
2777 DB_ROW row;
2778 zbx_uint64_t groupid, templateid;
2779 zbx_vector_uint64_t lnk_templateids, del_templateids,
2780 new_groupids, del_groupids;
2781 int i;
2782
2783 zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __func__, actionid);
2784
2785 zbx_vector_uint64_create(&lnk_templateids);
2786 zbx_vector_uint64_create(&del_templateids);
2787 zbx_vector_uint64_create(&new_groupids);
2788 zbx_vector_uint64_create(&del_groupids);
2789
2790 result = DBselect(
2791 "select o.operationtype,g.groupid,t.templateid,oi.inventory_mode"
2792 " from operations o"
2793 " left join opgroup g on g.operationid=o.operationid"
2794 " left join optemplate t on t.operationid=o.operationid"
2795 " left join opinventory oi on oi.operationid=o.operationid"
2796 " where o.actionid=" ZBX_FS_UI64
2797 " order by o.operationid",
2798 actionid);
2799
2800 while (NULL != (row = DBfetch(result)))
2801 {
2802 int inventory_mode;
2803 unsigned char operationtype;
2804
2805 operationtype = (unsigned char)atoi(row[0]);
2806 ZBX_DBROW2UINT64(groupid, row[1]);
2807 ZBX_DBROW2UINT64(templateid, row[2]);
2808 inventory_mode = (SUCCEED == DBis_null(row[3]) ? 0 : atoi(row[3]));
2809
2810 switch (operationtype)
2811 {
2812 case OPERATION_TYPE_HOST_ADD:
2813 op_host_add(event);
2814 break;
2815 case OPERATION_TYPE_HOST_REMOVE:
2816 op_host_del(event);
2817 break;
2818 case OPERATION_TYPE_HOST_ENABLE:
2819 op_host_enable(event);
2820 break;
2821 case OPERATION_TYPE_HOST_DISABLE:
2822 op_host_disable(event);
2823 break;
2824 case OPERATION_TYPE_GROUP_ADD:
2825 if (0 != groupid)
2826 zbx_vector_uint64_append(&new_groupids, groupid);
2827 break;
2828 case OPERATION_TYPE_GROUP_REMOVE:
2829 if (0 != groupid)
2830 zbx_vector_uint64_append(&del_groupids, groupid);
2831 break;
2832 case OPERATION_TYPE_TEMPLATE_ADD:
2833 if (0 != templateid)
2834 {
2835 if (FAIL != (i = zbx_vector_uint64_search(&del_templateids, templateid,
2836 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2837 {
2838 zbx_vector_uint64_remove(&del_templateids, i);
2839 }
2840
2841 zbx_vector_uint64_append(&lnk_templateids, templateid);
2842 }
2843 break;
2844 case OPERATION_TYPE_TEMPLATE_REMOVE:
2845 if (0 != templateid)
2846 {
2847 if (FAIL != (i = zbx_vector_uint64_search(&lnk_templateids, templateid,
2848 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2849 {
2850 zbx_vector_uint64_remove(&lnk_templateids, i);
2851 }
2852
2853 zbx_vector_uint64_append(&del_templateids, templateid);
2854 }
2855 break;
2856 case OPERATION_TYPE_HOST_INVENTORY:
2857 op_host_inventory_mode(event, inventory_mode);
2858 break;
2859 default:
2860 ;
2861 }
2862 }
2863 DBfree_result(result);
2864
2865 if (0 != del_templateids.values_num)
2866 {
2867 zbx_vector_uint64_sort(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2868 zbx_vector_uint64_uniq(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2869 op_template_del(event, &del_templateids);
2870 }
2871
2872 if (0 != lnk_templateids.values_num)
2873 {
2874 zbx_vector_uint64_sort(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2875 zbx_vector_uint64_uniq(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2876 op_template_add(event, &lnk_templateids);
2877 }
2878
2879 if (0 != new_groupids.values_num)
2880 {
2881 zbx_vector_uint64_sort(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2882 zbx_vector_uint64_uniq(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2883 op_groups_add(event, &new_groupids);
2884 }
2885
2886 if (0 != del_groupids.values_num)
2887 {
2888 zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2889 zbx_vector_uint64_uniq(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2890 op_groups_del(event, &del_groupids);
2891 }
2892
2893 zbx_vector_uint64_destroy(&del_groupids);
2894 zbx_vector_uint64_destroy(&new_groupids);
2895 zbx_vector_uint64_destroy(&del_templateids);
2896 zbx_vector_uint64_destroy(&lnk_templateids);
2897
2898 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2899 }
2900
2901 /* data structures used to create new and recover existing escalations */
2902
2903 typedef struct
2904 {
2905 zbx_uint64_t actionid;
2906 const DB_EVENT *event;
2907 }
2908 zbx_escalation_new_t;
2909
2910 /******************************************************************************
2911 * *
2912 * Function: is_recovery_event *
2913 * *
2914 * Purpose: checks if the event is recovery event *
2915 * *
2916 * Parameters: event - [IN] the event to check *
2917 * *
2918 * Return value: SUCCEED - the event is recovery event *
2919 * FAIL - otherwise *
2920 * *
2921 ******************************************************************************/
is_recovery_event(const DB_EVENT * event)2922 static int is_recovery_event(const DB_EVENT *event)
2923 {
2924 if (EVENT_SOURCE_TRIGGERS == event->source)
2925 {
2926 if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_VALUE_OK == event->value)
2927 return SUCCEED;
2928 }
2929 else if (EVENT_SOURCE_INTERNAL == event->source)
2930 {
2931 switch (event->object)
2932 {
2933 case EVENT_OBJECT_TRIGGER:
2934 if (TRIGGER_STATE_NORMAL == event->value)
2935 return SUCCEED;
2936 break;
2937 case EVENT_OBJECT_ITEM:
2938 if (ITEM_STATE_NORMAL == event->value)
2939 return SUCCEED;
2940 break;
2941 case EVENT_OBJECT_LLDRULE:
2942 if (ITEM_STATE_NORMAL == event->value)
2943 return SUCCEED;
2944 break;
2945 }
2946 }
2947
2948 return FAIL;
2949 }
2950
2951 /******************************************************************************
2952 * *
2953 * Function: is_escalation_event *
2954 * *
2955 * Purpose: to determine if event needs condition checks *
2956 * *
2957 * Parameters: event - [IN] event to validate *
2958 * *
2959 * Return value: SUCCEED - escalations possible for event *
2960 * FAIL - escalations not possible for event *
2961 * *
2962 ******************************************************************************/
is_escalation_event(const DB_EVENT * event)2963 static int is_escalation_event(const DB_EVENT *event)
2964 {
2965 /* OK events can't start escalations - skip them */
2966 if (SUCCEED == is_recovery_event(event))
2967 return FAIL;
2968
2969 if (0 != (event->flags & ZBX_FLAGS_DB_EVENT_NO_ACTION))
2970 return FAIL;
2971
2972 if (0 == (event->flags & ZBX_FLAGS_DB_EVENT_CREATE))
2973 return FAIL;
2974
2975 return SUCCEED;
2976 }
2977
2978 /******************************************************************************
2979 * *
2980 * Function: uniq_conditions_compare_func *
2981 * *
2982 * Purpose: compare to find equal conditions *
2983 * *
2984 * Parameters: d1 - [IN] condition structure to compare to d2 *
2985 * d2 - [IN] condition structure to compare to d1 *
2986 * *
2987 * Return value: 0 - equal *
2988 * not 0 - otherwise *
2989 * *
2990 ******************************************************************************/
uniq_conditions_compare_func(const void * d1,const void * d2)2991 static int uniq_conditions_compare_func(const void *d1, const void *d2)
2992 {
2993 const zbx_condition_t *condition1 = (const zbx_condition_t *)d1, *condition2 = (const zbx_condition_t *)d2;
2994 int ret;
2995
2996 ZBX_RETURN_IF_NOT_EQUAL(condition1->conditiontype, condition2->conditiontype);
2997 ZBX_RETURN_IF_NOT_EQUAL(condition1->op, condition2->op);
2998
2999 if (0 != (ret = strcmp(condition1->value, condition2->value)))
3000 return ret;
3001
3002 if (0 != (ret = strcmp(condition1->value2, condition2->value2)))
3003 return ret;
3004
3005 return 0;
3006 }
3007
3008 /******************************************************************************
3009 * *
3010 * Function: uniq_conditions_hash_func *
3011 * *
3012 * Purpose: generate hash based on condition values *
3013 * *
3014 * Parameters: data - [IN] condition structure *
3015 * *
3016 * *
3017 * Return value: hash is generated *
3018 * *
3019 ******************************************************************************/
uniq_conditions_hash_func(const void * data)3020 static zbx_hash_t uniq_conditions_hash_func(const void *data)
3021 {
3022 const zbx_condition_t *condition = (const zbx_condition_t *)data;
3023 zbx_hash_t hash;
3024
3025 hash = ZBX_DEFAULT_STRING_HASH_ALGO(condition->value, strlen(condition->value), ZBX_DEFAULT_HASH_SEED);
3026 hash = ZBX_DEFAULT_STRING_HASH_ALGO(condition->value2, strlen(condition->value2), hash);
3027 hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&condition->conditiontype, 1, hash);
3028 hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&condition->op, 1, hash);
3029
3030 return hash;
3031 }
3032
3033 /******************************************************************************
3034 * *
3035 * Function: get_escalation_events *
3036 * *
3037 * Purpose: add events that have escalation possible and skip others, also *
3038 * adds according to source *
3039 * *
3040 * Parameters: events - [IN] events to apply actions for *
3041 * events_num - [IN] number of events *
3042 * esc_events - [OUT] events that need condition checks *
3043 * *
3044 ******************************************************************************/
get_escalation_events(const zbx_vector_ptr_t * events,zbx_vector_ptr_t * esc_events)3045 static void get_escalation_events(const zbx_vector_ptr_t *events, zbx_vector_ptr_t *esc_events)
3046 {
3047 const DB_EVENT *event;
3048 int i;
3049
3050 for (i = 0; i < events->values_num; i++)
3051 {
3052 event = (DB_EVENT *)events->values[i];
3053 if (SUCCEED == is_escalation_event(event) && EVENT_SOURCE_COUNT > (size_t)event->source)
3054 zbx_vector_ptr_append(&esc_events[event->source], (void*)event);
3055 }
3056 }
3057
3058 /******************************************************************************
3059 * *
3060 * Function: db_condition_clean *
3061 * *
3062 * Purpose: cleans condition data structure *
3063 * *
3064 * Parameters: condition - [IN] the condition data to free *
3065 * *
3066 ******************************************************************************/
db_condition_clean(zbx_condition_t * condition)3067 static void db_condition_clean(zbx_condition_t *condition)
3068 {
3069 zbx_free(condition->value2);
3070 zbx_free(condition->value);
3071 zbx_vector_uint64_destroy(&condition->eventids);
3072 }
3073
3074 /******************************************************************************
3075 * *
3076 * Function: zbx_conditions_eval_clean *
3077 * *
3078 * Purpose: cleans condition data structures from hashset *
3079 * *
3080 * Parameters: uniq_conditions - [IN] hashset with data structures to clean *
3081 * *
3082 ******************************************************************************/
conditions_eval_clean(zbx_hashset_t * uniq_conditions)3083 static void conditions_eval_clean(zbx_hashset_t *uniq_conditions)
3084 {
3085 zbx_hashset_iter_t iter;
3086 zbx_condition_t *condition;
3087
3088 zbx_hashset_iter_reset(uniq_conditions, &iter);
3089
3090 while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3091 db_condition_clean(condition);
3092 }
3093
3094 /******************************************************************************
3095 * *
3096 * Function: zbx_action_eval_free *
3097 * *
3098 * Purpose: frees action evaluation data structure *
3099 * *
3100 * Parameters: action - [IN] the action evaluation to free *
3101 * *
3102 ******************************************************************************/
zbx_action_eval_free(zbx_action_eval_t * action)3103 static void zbx_action_eval_free(zbx_action_eval_t *action)
3104 {
3105 zbx_free(action->formula);
3106
3107 zbx_vector_ptr_destroy(&action->conditions);
3108
3109 zbx_free(action);
3110 }
3111
3112 /******************************************************************************
3113 * *
3114 * Function: prepare_actions_conditions_eval *
3115 * *
3116 * Purpose: make actions to point, to conditions from hashset, where all *
3117 * conditions are unique, this ensures that we don't double check *
3118 * same conditions. *
3119 * *
3120 * Parameters: actions - [IN/OUT] all conditions are added to hashset *
3121 * then cleaned, actions will now *
3122 * point to conditions from hashset. *
3123 * for custom expression also *
3124 * replaces formula *
3125 * uniq_conditions - [OUT] unique conditions that actions *
3126 * point to (several sources) *
3127 * *
3128 * Comments: The returned conditions must be freed with *
3129 * conditions_eval_clean() function later. *
3130 * *
3131 ******************************************************************************/
prepare_actions_conditions_eval(zbx_vector_ptr_t * actions,zbx_hashset_t * uniq_conditions)3132 static void prepare_actions_conditions_eval(zbx_vector_ptr_t *actions, zbx_hashset_t *uniq_conditions)
3133 {
3134 int i, j;
3135
3136 for (i = 0; i < actions->values_num; i++)
3137 {
3138 zbx_action_eval_t *action = actions->values[i];
3139
3140 for (j = 0; j < action->conditions.values_num; j++)
3141 {
3142 zbx_condition_t *uniq_condition = NULL, *condition = action->conditions.values[j];
3143
3144 if (EVENT_SOURCE_COUNT <= action->eventsource)
3145 {
3146 db_condition_clean(condition);
3147 }
3148 else if (NULL == (uniq_condition = zbx_hashset_search(&uniq_conditions[action->eventsource],
3149 condition)))
3150 {
3151 uniq_condition = zbx_hashset_insert(&uniq_conditions[action->eventsource],
3152 condition, sizeof(zbx_condition_t));
3153 }
3154 else
3155 {
3156 if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
3157 {
3158 char search[ZBX_MAX_UINT64_LEN + 2];
3159 char replace[ZBX_MAX_UINT64_LEN + 2];
3160 char *old_formula;
3161
3162 zbx_snprintf(search, sizeof(search), "{" ZBX_FS_UI64 "}",
3163 condition->conditionid);
3164 zbx_snprintf(replace, sizeof(replace), "{" ZBX_FS_UI64 "}",
3165 uniq_condition->conditionid);
3166
3167 old_formula = action->formula;
3168 action->formula = string_replace(action->formula, search, replace);
3169 zbx_free(old_formula);
3170 }
3171
3172 db_condition_clean(condition);
3173 }
3174
3175 zbx_free(action->conditions.values[j]);
3176 action->conditions.values[j] = uniq_condition;
3177 }
3178 }
3179 }
3180
3181 /******************************************************************************
3182 * *
3183 * Function: process_actions *
3184 * *
3185 * Purpose: process all actions of each event in a list *
3186 * *
3187 * Parameters: events - [IN] events to apply actions for *
3188 * closed_events - [IN] a vector of closed event data - *
3189 * (PROBLEM eventid, OK eventid) pairs. *
3190 * *
3191 ******************************************************************************/
process_actions(const zbx_vector_ptr_t * events,const zbx_vector_uint64_pair_t * closed_events)3192 void process_actions(const zbx_vector_ptr_t *events, const zbx_vector_uint64_pair_t *closed_events)
3193 {
3194 int i;
3195 zbx_vector_ptr_t actions;
3196 zbx_vector_ptr_t new_escalations;
3197 zbx_vector_uint64_pair_t rec_escalations;
3198 zbx_hashset_t uniq_conditions[EVENT_SOURCE_COUNT];
3199 zbx_vector_ptr_t esc_events[EVENT_SOURCE_COUNT];
3200 zbx_hashset_iter_t iter;
3201 zbx_condition_t *condition;
3202
3203 zabbix_log(LOG_LEVEL_DEBUG, "In %s() events_num:" ZBX_FS_SIZE_T, __func__, (zbx_fs_size_t)events->values_num);
3204
3205 zbx_vector_ptr_create(&new_escalations);
3206 zbx_vector_uint64_pair_create(&rec_escalations);
3207
3208 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3209 {
3210 zbx_hashset_create(&uniq_conditions[i], 0, uniq_conditions_hash_func, uniq_conditions_compare_func);
3211 zbx_vector_ptr_create(&esc_events[i]);
3212 }
3213
3214 zbx_vector_ptr_create(&actions);
3215 zbx_dc_get_actions_eval(&actions, ZBX_ACTION_OPCLASS_NORMAL | ZBX_ACTION_OPCLASS_RECOVERY);
3216 prepare_actions_conditions_eval(&actions, uniq_conditions);
3217 get_escalation_events(events, esc_events);
3218
3219 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3220 {
3221 if (0 == esc_events[i].values_num)
3222 continue;
3223
3224 zbx_vector_ptr_sort(&esc_events[i], compare_events);
3225
3226 zbx_hashset_iter_reset(&uniq_conditions[i], &iter);
3227
3228 while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3229 check_events_condition(&esc_events[i], i, condition);
3230 }
3231
3232 /* 1. All event sources: match PROBLEM events to action conditions, add them to 'new_escalations' list. */
3233 /* 2. EVENT_SOURCE_DISCOVERY, EVENT_SOURCE_AUTOREGISTRATION: execute operations (except command and message */
3234 /* operations) for events that match action conditions. */
3235 for (i = 0; i < events->values_num; i++)
3236 {
3237 int j;
3238 const DB_EVENT *event;
3239
3240 if (FAIL == is_escalation_event((event = (const DB_EVENT *)events->values[i])))
3241 continue;
3242
3243 for (j = 0; j < actions.values_num; j++)
3244 {
3245 zbx_action_eval_t *action = (zbx_action_eval_t *)actions.values[j];
3246
3247 if (action->eventsource != event->source)
3248 continue;
3249
3250 if (SUCCEED == check_action_conditions(event->eventid, action))
3251 {
3252 zbx_escalation_new_t *new_escalation;
3253
3254 /* command and message operations handled by escalators even for */
3255 /* EVENT_SOURCE_DISCOVERY and EVENT_SOURCE_AUTOREGISTRATION events */
3256 new_escalation = (zbx_escalation_new_t *)zbx_malloc(NULL, sizeof(zbx_escalation_new_t));
3257 new_escalation->actionid = action->actionid;
3258 new_escalation->event = event;
3259 zbx_vector_ptr_append(&new_escalations, new_escalation);
3260
3261 if (EVENT_SOURCE_DISCOVERY == event->source ||
3262 EVENT_SOURCE_AUTOREGISTRATION == event->source)
3263 {
3264 execute_operations(event, action->actionid);
3265 }
3266 }
3267 }
3268 }
3269
3270 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3271 {
3272 zbx_vector_ptr_destroy(&esc_events[i]);
3273 conditions_eval_clean(&uniq_conditions[i]);
3274 zbx_hashset_destroy(&uniq_conditions[i]);
3275 }
3276
3277 zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free);
3278 zbx_vector_ptr_destroy(&actions);
3279
3280 /* 3. Find recovered escalations and store escalationids in 'rec_escalation' by OK eventids. */
3281 if (0 != closed_events->values_num)
3282 {
3283 char *sql = NULL;
3284 size_t sql_alloc = 0, sql_offset = 0;
3285 zbx_vector_uint64_t eventids;
3286 DB_ROW row;
3287 DB_RESULT result;
3288 int j, index;
3289
3290 zbx_vector_uint64_create(&eventids);
3291
3292 /* 3.1. Store PROBLEM eventids of recovered events in 'eventids'. */
3293 for (j = 0; j < closed_events->values_num; j++)
3294 zbx_vector_uint64_append(&eventids, closed_events->values[j].first);
3295
3296 /* 3.2. Select escalations that must be recovered. */
3297 zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3298 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3299 "select eventid,escalationid"
3300 " from escalations"
3301 " where");
3302
3303 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "eventid", eventids.values, eventids.values_num);
3304 result = DBselect("%s", sql);
3305
3306 zbx_vector_uint64_pair_reserve(&rec_escalations, eventids.values_num);
3307
3308 /* 3.3. Store the escalationids corresponding to the OK events in 'rec_escalations'. */
3309 while (NULL != (row = DBfetch(result)))
3310 {
3311 zbx_uint64_pair_t pair;
3312
3313 ZBX_STR2UINT64(pair.first, row[0]);
3314
3315 if (FAIL == (index = zbx_vector_uint64_pair_bsearch(closed_events, pair,
3316 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3317 {
3318 THIS_SHOULD_NEVER_HAPPEN;
3319 continue;
3320 }
3321
3322 pair.second = closed_events->values[index].second;
3323 ZBX_DBROW2UINT64(pair.first, row[1]);
3324 zbx_vector_uint64_pair_append(&rec_escalations, pair);
3325 }
3326
3327 DBfree_result(result);
3328 zbx_free(sql);
3329 zbx_vector_uint64_destroy(&eventids);
3330 }
3331
3332 /* 4. Create new escalations in DB. */
3333 if (0 != new_escalations.values_num)
3334 {
3335 zbx_db_insert_t db_insert;
3336 int j;
3337
3338 zbx_db_insert_prepare(&db_insert, "escalations", "escalationid", "actionid", "status", "triggerid",
3339 "itemid", "eventid", "r_eventid", "acknowledgeid", NULL);
3340
3341 for (j = 0; j < new_escalations.values_num; j++)
3342 {
3343 zbx_uint64_t triggerid = 0, itemid = 0;
3344 zbx_escalation_new_t *new_escalation;
3345
3346 new_escalation = (zbx_escalation_new_t *)new_escalations.values[j];
3347
3348 switch (new_escalation->event->object)
3349 {
3350 case EVENT_OBJECT_TRIGGER:
3351 triggerid = new_escalation->event->objectid;
3352 break;
3353 case EVENT_OBJECT_ITEM:
3354 case EVENT_OBJECT_LLDRULE:
3355 itemid = new_escalation->event->objectid;
3356 break;
3357 }
3358
3359 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), new_escalation->actionid,
3360 (int)ESCALATION_STATUS_ACTIVE, triggerid, itemid,
3361 new_escalation->event->eventid, __UINT64_C(0), __UINT64_C(0));
3362
3363 zbx_free(new_escalation);
3364 }
3365
3366 zbx_db_insert_autoincrement(&db_insert, "escalationid");
3367 zbx_db_insert_execute(&db_insert);
3368 zbx_db_insert_clean(&db_insert);
3369 }
3370
3371 /* 5. Modify recovered escalations in DB. */
3372 if (0 != rec_escalations.values_num)
3373 {
3374 char *sql = NULL;
3375 size_t sql_alloc = 0, sql_offset = 0;
3376 int j;
3377
3378 zbx_vector_uint64_pair_sort(&rec_escalations, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3379
3380 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3381
3382 for (j = 0; j < rec_escalations.values_num; j++)
3383 {
3384 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3385 "update escalations set r_eventid=" ZBX_FS_UI64 ",nextcheck=0"
3386 " where escalationid=" ZBX_FS_UI64 ";\n",
3387 rec_escalations.values[j].second, rec_escalations.values[j].first);
3388
3389 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3390 }
3391
3392 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3393
3394 if (16 < sql_offset) /* in ORACLE always present begin..end; */
3395 DBexecute("%s", sql);
3396
3397 zbx_free(sql);
3398 }
3399
3400 zbx_vector_uint64_pair_destroy(&rec_escalations);
3401 zbx_vector_ptr_destroy(&new_escalations);
3402
3403 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3404 }
3405
3406 /******************************************************************************
3407 * *
3408 * Function: process_actions_by_acknowledgements *
3409 * *
3410 * Purpose: process actions for each acknowledgement in the array *
3411 * *
3412 * Parameters: event_ack - [IN] vector for eventid/ackid pairs *
3413 * *
3414 ******************************************************************************/
process_actions_by_acknowledgements(const zbx_vector_ptr_t * ack_tasks)3415 int process_actions_by_acknowledgements(const zbx_vector_ptr_t *ack_tasks)
3416 {
3417 zbx_vector_ptr_t actions;
3418 zbx_hashset_t uniq_conditions[EVENT_SOURCE_COUNT];
3419 int i, j, k, processed_num = 0, knext = 0;
3420 zbx_vector_uint64_t eventids;
3421 zbx_ack_task_t *ack_task;
3422 zbx_vector_ptr_t ack_escalations, events;
3423 zbx_ack_escalation_t *ack_escalation;
3424 zbx_vector_ptr_t esc_events[EVENT_SOURCE_COUNT];
3425 zbx_hashset_iter_t iter;
3426 zbx_condition_t *condition;
3427
3428 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3429
3430 zbx_vector_ptr_create(&ack_escalations);
3431
3432 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3433 {
3434 zbx_hashset_create(&uniq_conditions[i], 0, uniq_conditions_hash_func, uniq_conditions_compare_func);
3435 zbx_vector_ptr_create(&esc_events[i]);
3436 }
3437
3438 zbx_vector_ptr_create(&actions);
3439 zbx_dc_get_actions_eval(&actions, ZBX_ACTION_OPCLASS_ACKNOWLEDGE);
3440 prepare_actions_conditions_eval(&actions, uniq_conditions);
3441
3442 if (0 == actions.values_num)
3443 goto out;
3444
3445 zbx_vector_uint64_create(&eventids);
3446
3447 for (i = 0; i < ack_tasks->values_num; i++)
3448 {
3449 ack_task = (zbx_ack_task_t *)ack_tasks->values[i];
3450 zbx_vector_uint64_append(&eventids, ack_task->eventid);
3451 }
3452
3453 zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3454 zbx_vector_uint64_uniq(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3455
3456 zbx_vector_ptr_create(&events);
3457
3458 zbx_db_get_events_by_eventids(&eventids, &events);
3459
3460 for (i = 0; i < events.values_num; i++)
3461 {
3462 DB_EVENT *event = (DB_EVENT *)events.values[i];
3463
3464 zbx_vector_ptr_append(&esc_events[event->source], (void*)event);
3465 }
3466
3467 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3468 {
3469 if (0 == esc_events[i].values_num)
3470 continue;
3471
3472 zbx_vector_ptr_sort(&esc_events[i], compare_events);
3473
3474 zbx_hashset_iter_reset(&uniq_conditions[i], &iter);
3475
3476 while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3477 check_events_condition(&esc_events[i], i, condition);
3478 }
3479
3480 for (i = 0; i < eventids.values_num; i++)
3481 {
3482 int kcurr = knext;
3483 DB_EVENT *event = (DB_EVENT *)events.values[i];
3484
3485 while (knext < ack_tasks->values_num)
3486 {
3487 ack_task = (zbx_ack_task_t *)ack_tasks->values[knext];
3488 if (ack_task->eventid != event->eventid)
3489 break;
3490 knext++;
3491 }
3492
3493 if (0 == event->eventid || 0 == event->trigger.triggerid)
3494 continue;
3495
3496 for (j = 0; j < actions.values_num; j++)
3497 {
3498 zbx_action_eval_t *action = (zbx_action_eval_t *)actions.values[j];
3499
3500 if (action->eventsource != event->source)
3501 continue;
3502
3503 if (SUCCEED != check_action_conditions(event->eventid, action))
3504 continue;
3505
3506 for (k = kcurr; k < knext; k++)
3507 {
3508 ack_task = (zbx_ack_task_t *)ack_tasks->values[k];
3509
3510 ack_escalation = (zbx_ack_escalation_t *)zbx_malloc(NULL, sizeof(zbx_ack_escalation_t));
3511 ack_escalation->taskid = ack_task->taskid;
3512 ack_escalation->acknowledgeid = ack_task->acknowledgeid;
3513 ack_escalation->actionid = action->actionid;
3514 ack_escalation->eventid = event->eventid;
3515 ack_escalation->triggerid = event->trigger.triggerid;
3516 zbx_vector_ptr_append(&ack_escalations, ack_escalation);
3517 }
3518 }
3519 }
3520
3521 if (0 != ack_escalations.values_num)
3522 {
3523 zbx_db_insert_t db_insert;
3524
3525 zbx_db_insert_prepare(&db_insert, "escalations", "escalationid", "actionid", "status", "triggerid",
3526 "itemid", "eventid", "r_eventid", "acknowledgeid", NULL);
3527
3528 zbx_vector_ptr_sort(&ack_escalations, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3529
3530 for (i = 0; i < ack_escalations.values_num; i++)
3531 {
3532 ack_escalation = (zbx_ack_escalation_t *)ack_escalations.values[i];
3533
3534 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), ack_escalation->actionid,
3535 (int)ESCALATION_STATUS_ACTIVE, ack_escalation->triggerid, __UINT64_C(0),
3536 ack_escalation->eventid, __UINT64_C(0), ack_escalation->acknowledgeid);
3537 }
3538
3539 zbx_db_insert_autoincrement(&db_insert, "escalationid");
3540 zbx_db_insert_execute(&db_insert);
3541 zbx_db_insert_clean(&db_insert);
3542
3543 processed_num = ack_escalations.values_num;
3544 }
3545
3546 zbx_vector_ptr_clear_ext(&events, (zbx_clean_func_t)zbx_db_free_event);
3547 zbx_vector_ptr_destroy(&events);
3548
3549 zbx_vector_uint64_destroy(&eventids);
3550 out:
3551 for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3552 {
3553 zbx_vector_ptr_destroy(&esc_events[i]);
3554 conditions_eval_clean(&uniq_conditions[i]);
3555 zbx_hashset_destroy(&uniq_conditions[i]);
3556 }
3557
3558 zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free);
3559 zbx_vector_ptr_destroy(&actions);
3560
3561 zbx_vector_ptr_clear_ext(&ack_escalations, zbx_ptr_free);
3562 zbx_vector_ptr_destroy(&ack_escalations);
3563
3564 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() processed_num:%d", __func__, processed_num);
3565
3566 return processed_num;
3567 }
3568
3569 /******************************************************************************
3570 * *
3571 * Function: get_actions_info *
3572 * *
3573 * Purpose: reads actions from database *
3574 * *
3575 * Parameters: actionids - [IN] requested action ids *
3576 * actions - [OUT] the array of actions *
3577 * *
3578 * Comments: use 'free_db_action' function to release allocated memory *
3579 * *
3580 ******************************************************************************/
get_db_actions_info(zbx_vector_uint64_t * actionids,zbx_vector_ptr_t * actions)3581 void get_db_actions_info(zbx_vector_uint64_t *actionids, zbx_vector_ptr_t *actions)
3582 {
3583 DB_RESULT result;
3584 DB_ROW row;
3585 char *filter = NULL;
3586 size_t filter_alloc = 0, filter_offset = 0;
3587 DB_ACTION *action;
3588
3589 zbx_vector_uint64_sort(actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3590 zbx_vector_uint64_uniq(actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3591
3592 DBadd_condition_alloc(&filter, &filter_alloc, &filter_offset, "actionid", actionids->values,
3593 actionids->values_num);
3594
3595 result = DBselect("select actionid,name,status,eventsource,esc_period,pause_suppressed"
3596 " from actions"
3597 " where%s order by actionid", filter);
3598
3599 while (NULL != (row = DBfetch(result)))
3600 {
3601 char *tmp;
3602
3603 action = (DB_ACTION *)zbx_malloc(NULL, sizeof(DB_ACTION));
3604 ZBX_STR2UINT64(action->actionid, row[0]);
3605 ZBX_STR2UCHAR(action->status, row[2]);
3606 ZBX_STR2UCHAR(action->eventsource, row[3]);
3607
3608 tmp = zbx_strdup(NULL, row[4]);
3609 substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &tmp,
3610 MACRO_TYPE_COMMON, NULL, 0);
3611 if (SUCCEED != is_time_suffix(tmp, &action->esc_period, ZBX_LENGTH_UNLIMITED))
3612 {
3613 zabbix_log(LOG_LEVEL_WARNING, "Invalid default operation step duration \"%s\" for action"
3614 " \"%s\", using default value of 1 hour", tmp, row[1]);
3615 action->esc_period = SEC_PER_HOUR;
3616 }
3617 zbx_free(tmp);
3618
3619 ZBX_STR2UCHAR(action->pause_suppressed, row[5]);
3620 action->name = zbx_strdup(NULL, row[1]);
3621 action->recovery = ZBX_ACTION_RECOVERY_NONE;
3622
3623 zbx_vector_ptr_append(actions, action);
3624 }
3625 DBfree_result(result);
3626
3627 result = DBselect("select actionid from operations where recovery=%d and%s",
3628 ZBX_OPERATION_MODE_RECOVERY, filter);
3629
3630 while (NULL != (row = DBfetch(result)))
3631 {
3632 zbx_uint64_t actionid;
3633 int index;
3634
3635 ZBX_STR2UINT64(actionid, row[0]);
3636 if (FAIL != (index = zbx_vector_ptr_bsearch(actions, &actionid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3637 {
3638 action = (DB_ACTION *)actions->values[index];
3639 action->recovery = ZBX_ACTION_RECOVERY_OPERATIONS;
3640 }
3641 }
3642 DBfree_result(result);
3643
3644 zbx_free(filter);
3645 }
3646
free_db_action(DB_ACTION * action)3647 void free_db_action(DB_ACTION *action)
3648 {
3649 zbx_free(action->name);
3650 zbx_free(action);
3651 }
3652