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