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, &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, &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_application_condition                                      *
825  *                                                                            *
826  * Purpose: check application condition                                       *
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  * Return value: SUCCEED - supported operator                                 *
833  *               NOTSUPPORTED - not supported operator                        *
834  *                                                                            *
835  ******************************************************************************/
check_application_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)836 static int	check_application_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
837 {
838 	char			*sql = NULL;
839 	size_t			sql_alloc = 0, sql_offset = 0;
840 	DB_RESULT		result;
841 	DB_ROW			row;
842 	zbx_vector_uint64_t	objectids;
843 	zbx_uint64_t		objectid;
844 	int			i;
845 
846 	if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_LIKE != condition->op &&
847 			CONDITION_OPERATOR_NOT_LIKE != condition->op)
848 	{
849 		return NOTSUPPORTED;
850 	}
851 
852 	zbx_vector_uint64_create(&objectids);
853 
854 	get_object_ids(esc_events, &objectids);
855 
856 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
857 			"select distinct t.triggerid,a.name"
858 			" from applications a,items_applications i,functions f,triggers t"
859 			" where a.applicationid=i.applicationid"
860 			" and i.itemid=f.itemid"
861 			" and f.triggerid=t.triggerid"
862 			" and");
863 
864 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid", objectids.values, objectids.values_num);
865 
866 	result = DBselect("%s", sql);
867 
868 	switch (condition->op)
869 	{
870 		case CONDITION_OPERATOR_EQUAL:
871 			while (NULL != (row = DBfetch(result)))
872 			{
873 				if (0 == strcmp(row[1], condition->value))
874 				{
875 					ZBX_STR2UINT64(objectid, row[0]);
876 					add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER);
877 				}
878 			}
879 			break;
880 		case CONDITION_OPERATOR_LIKE:
881 			while (NULL != (row = DBfetch(result)))
882 			{
883 				if (NULL != strstr(row[1], condition->value))
884 				{
885 					ZBX_STR2UINT64(objectid, row[0]);
886 					add_condition_match(esc_events, condition, objectid, EVENT_OBJECT_TRIGGER);
887 				}
888 			}
889 			break;
890 		case CONDITION_OPERATOR_NOT_LIKE:
891 			while (NULL != (row = DBfetch(result)))
892 			{
893 				if (NULL != strstr(row[1], condition->value))
894 				{
895 					ZBX_STR2UINT64(objectid, row[0]);
896 
897 					if (FAIL != (i = zbx_vector_uint64_search(&objectids, objectid,
898 							ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
899 					{
900 						zbx_vector_uint64_remove_noorder(&objectids, i);
901 					}
902 				}
903 			}
904 
905 			for (i = 0; i < objectids.values_num; i++)
906 				add_condition_match(esc_events, condition, objectids.values[i], EVENT_OBJECT_TRIGGER);
907 			break;
908 	}
909 	DBfree_result(result);
910 
911 	zbx_vector_uint64_destroy(&objectids);
912 	zbx_free(sql);
913 
914 	return SUCCEED;
915 }
916 
917 /******************************************************************************
918  *                                                                            *
919  * Function: check_condition_event_tag                                        *
920  *                                                                            *
921  * Purpose: check condition event tag                                         *
922  *                                                                            *
923  * Parameters: esc_events - [IN] events to check                              *
924  *             condition  - [IN/OUT] condition for matching, outputs          *
925  *                                   event ids that match condition           *
926  *                                                                            *
927  ******************************************************************************/
check_condition_event_tag(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)928 static void	check_condition_event_tag(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
929 {
930 	int	i, ret, ret_continue;
931 
932 	if (CONDITION_OPERATOR_NOT_EQUAL == condition->op || CONDITION_OPERATOR_NOT_LIKE == condition->op)
933 		ret_continue = SUCCEED;
934 	else
935 		ret_continue = FAIL;
936 
937 	for (i = 0; i < esc_events->values_num; i++)
938 	{
939 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
940 		int		j;
941 
942 		ret = ret_continue;
943 
944 		for (j = 0; j < event->tags.values_num && ret == ret_continue; j++)
945 		{
946 			const zbx_tag_t	*tag = (zbx_tag_t *)event->tags.values[j];
947 
948 			ret = zbx_strmatch_condition(tag->tag, condition->value, condition->op);
949 		}
950 
951 		if (SUCCEED == ret)
952 			zbx_vector_uint64_append(&condition->eventids, event->eventid);
953 	}
954 }
955 
956 /******************************************************************************
957  *                                                                            *
958  * Function: check_condition_event_tag_value                                  *
959  *                                                                            *
960  * Purpose: check condition event tag value                                   *
961  *                                                                            *
962  * Parameters: esc_events - [IN] events to check                              *
963  *             condition  - [IN/OUT] condition for matching, outputs          *
964  *                                   event ids that match condition           *
965  *                                                                            *
966  ******************************************************************************/
check_condition_event_tag_value(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)967 static void	check_condition_event_tag_value(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
968 {
969 	int	i, ret, ret_continue;
970 
971 	if (CONDITION_OPERATOR_NOT_EQUAL == condition->op || CONDITION_OPERATOR_NOT_LIKE == condition->op)
972 		ret_continue = SUCCEED;
973 	else
974 		ret_continue = FAIL;
975 
976 	for (i = 0; i < esc_events->values_num; i++)
977 	{
978 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
979 		int		j;
980 
981 		ret = ret_continue;
982 
983 		for (j = 0; j < event->tags.values_num && ret == ret_continue; j++)
984 		{
985 			zbx_tag_t	*tag = (zbx_tag_t *)event->tags.values[j];
986 
987 			if (0 == strcmp(condition->value2, tag->tag))
988 				ret = zbx_strmatch_condition(tag->value, condition->value, condition->op);
989 		}
990 
991 		if (SUCCEED == ret)
992 			zbx_vector_uint64_append(&condition->eventids, event->eventid);
993 	}
994 }
995 
996 /******************************************************************************
997  *                                                                            *
998  * Function: check_trigger_condition                                          *
999  *                                                                            *
1000  * Purpose: check if event matches single condition                           *
1001  *                                                                            *
1002  * Parameters: event - trigger event to check                                 *
1003  *                                  (event->source == EVENT_SOURCE_TRIGGERS)  *
1004  *             condition - condition for matching                             *
1005  *                                                                            *
1006  * Return value: SUCCEED - matches, FAIL - otherwise                          *
1007  *                                                                            *
1008  * Author: Alexei Vladishev                                                   *
1009  *                                                                            *
1010  ******************************************************************************/
check_trigger_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1011 static void	check_trigger_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1012 {
1013 	int	ret;
1014 
1015 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1016 
1017 	switch (condition->conditiontype)
1018 	{
1019 		case CONDITION_TYPE_HOST_GROUP:
1020 			ret = check_host_group_condition(esc_events, condition);
1021 			break;
1022 		case CONDITION_TYPE_HOST_TEMPLATE:
1023 			ret = check_host_template_condition(esc_events, condition);
1024 			break;
1025 		case CONDITION_TYPE_HOST:
1026 			ret = check_host_condition(esc_events, condition);
1027 			break;
1028 		case CONDITION_TYPE_TRIGGER:
1029 			ret = check_trigger_id_condition(esc_events, condition);
1030 			break;
1031 		case CONDITION_TYPE_TRIGGER_NAME:
1032 			ret = check_trigger_name_condition(esc_events, condition);
1033 			break;
1034 		case CONDITION_TYPE_TRIGGER_SEVERITY:
1035 			ret = check_trigger_severity_condition(esc_events, condition);
1036 			break;
1037 		case CONDITION_TYPE_TIME_PERIOD:
1038 			ret = check_time_period_condition(esc_events, condition);
1039 			break;
1040 		case CONDITION_TYPE_SUPPRESSED:
1041 			ret = check_suppressed_condition(esc_events, condition);
1042 			break;
1043 		case CONDITION_TYPE_EVENT_ACKNOWLEDGED:
1044 			ret = check_acknowledged_condition(esc_events, condition);
1045 			break;
1046 		case CONDITION_TYPE_APPLICATION:
1047 			ret = check_application_condition(esc_events, condition);
1048 			break;
1049 		case CONDITION_TYPE_EVENT_TAG:
1050 			check_condition_event_tag(esc_events, condition);
1051 			ret = SUCCEED;
1052 			break;
1053 		case CONDITION_TYPE_EVENT_TAG_VALUE:
1054 			check_condition_event_tag_value(esc_events,condition);
1055 			ret = SUCCEED;
1056 			break;
1057 		default:
1058 			zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
1059 					(int)condition->conditiontype, condition->conditionid);
1060 			ret = FAIL;
1061 	}
1062 
1063 	if (NOTSUPPORTED == ret)
1064 	{
1065 		zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
1066 				(int)condition->op, condition->conditionid);
1067 	}
1068 
1069 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
1070 }
1071 
1072 /******************************************************************************
1073  *                                                                            *
1074  * Function: get_object_ids_discovery                                         *
1075  *                                                                            *
1076  * Purpose: get objectids for dhost                                           *
1077  *                                                                            *
1078  * Parameters: esc_events - [IN]  events to check                             *
1079  *             objectids  - [OUT] event objectids to be used in condition     *
1080  *                                allocation 2 vectors where first one is     *
1081  *                                dhost ids, second is dservice               *
1082 *                                                                             *
1083  ******************************************************************************/
get_object_ids_discovery(const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids)1084 static void	get_object_ids_discovery(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids)
1085 {
1086 	int	i;
1087 
1088 	for (i = 0; i < esc_events->values_num; i++)
1089 	{
1090 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
1091 
1092 		if (event->object == EVENT_OBJECT_DHOST)
1093 			zbx_vector_uint64_append(&objectids[0], event->objectid);
1094 		else
1095 			zbx_vector_uint64_append(&objectids[1], event->objectid);
1096 	}
1097 
1098 	zbx_vector_uint64_uniq(&objectids[0], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1099 	zbx_vector_uint64_uniq(&objectids[1], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1100 }
1101 /******************************************************************************
1102  *                                                                            *
1103  * Function: check_drule_condition                                            *
1104  *                                                                            *
1105  * Purpose: check discovery rule 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_drule_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1115 static int	check_drule_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1116 {
1117 	char			*sql = NULL, *operation_and, *operation_where;
1118 	size_t			sql_alloc = 0, i;
1119 	DB_RESULT		result;
1120 	DB_ROW			row;
1121 	int			objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1122 	zbx_vector_uint64_t	objectids[2];
1123 	zbx_uint64_t		condition_value;
1124 
1125 	if (CONDITION_OPERATOR_EQUAL == condition->op)
1126 	{
1127 		operation_and = " and";
1128 		operation_where = " where";
1129 	}
1130 	else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1131 	{
1132 		operation_and = " and not";
1133 		operation_where = " where not";
1134 	}
1135 	else
1136 		return NOTSUPPORTED;
1137 
1138 	ZBX_STR2UINT64(condition_value, condition->value);
1139 
1140 	zbx_vector_uint64_create(&objectids[0]);
1141 	zbx_vector_uint64_create(&objectids[1]);
1142 
1143 	get_object_ids_discovery(esc_events, objectids);
1144 
1145 	for (i = 0; i < (int)ARRSIZE(objects); i++)
1146 	{
1147 		size_t	sql_offset = 0;
1148 
1149 		if (0 == objectids[i].values_num)
1150 			continue;
1151 
1152 		if (EVENT_OBJECT_DHOST == objects[i])
1153 		{
1154 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1155 					"select dhostid"
1156 					" from dhosts"
1157 					"%s druleid=" ZBX_FS_UI64
1158 					" and",
1159 					operation_where,
1160 					condition_value);
1161 
1162 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid",
1163 					objectids[i].values, objectids[i].values_num);
1164 		}
1165 		else	/* EVENT_OBJECT_DSERVICE */
1166 		{
1167 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1168 					"select s.dserviceid"
1169 					" from dhosts h,dservices s"
1170 					" where h.dhostid=s.dhostid"
1171 						"%s h.druleid=" ZBX_FS_UI64
1172 						" and",
1173 					operation_and,
1174 					condition_value);
1175 
1176 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.dserviceid",
1177 					objectids[i].values, objectids[i].values_num);
1178 		}
1179 
1180 		result = DBselect("%s", sql);
1181 
1182 		while (NULL != (row = DBfetch(result)))
1183 		{
1184 			zbx_uint64_t	objectid;
1185 
1186 			ZBX_STR2UINT64(objectid, row[0]);
1187 			add_condition_match(esc_events, condition, objectid, objects[i]);
1188 		}
1189 		DBfree_result(result);
1190 	}
1191 
1192 	zbx_vector_uint64_destroy(&objectids[0]);
1193 	zbx_vector_uint64_destroy(&objectids[1]);
1194 	zbx_free(sql);
1195 
1196 	return SUCCEED;
1197 }
1198 
1199 /******************************************************************************
1200  *                                                                            *
1201  * Function: check_dcheck_condition                                           *
1202  *                                                                            *
1203  * Purpose: check discovery check condition                                   *
1204  *                                                                            *
1205  * Parameters: esc_events - [IN] events to check                              *
1206  *             condition  - [IN/OUT] condition for matching, outputs          *
1207  *                                   event ids that match condition           *
1208  *                                                                            *
1209  * Return value: SUCCEED - supported operator                                 *
1210  *               NOTSUPPORTED - not supported operator                        *
1211  *                                                                            *
1212  ******************************************************************************/
check_dcheck_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1213 static int	check_dcheck_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1214 {
1215 	char			*sql = NULL, *operation_where;
1216 	size_t			sql_alloc = 0, sql_offset = 0;
1217 	DB_RESULT		result;
1218 	DB_ROW			row;
1219 	int			object = EVENT_OBJECT_DSERVICE, i;
1220 	zbx_vector_uint64_t	objectids;
1221 	zbx_uint64_t		condition_value;
1222 
1223 	if (CONDITION_OPERATOR_EQUAL == condition->op)
1224 		operation_where = " where";
1225 	else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1226 		operation_where = " where not";
1227 	else
1228 		return NOTSUPPORTED;
1229 
1230 	ZBX_STR2UINT64(condition_value, condition->value);
1231 
1232 	zbx_vector_uint64_create(&objectids);
1233 
1234 	for (i = 0; i < esc_events->values_num; i++)
1235 	{
1236 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
1237 
1238 		if (object == event->object)
1239 			zbx_vector_uint64_append(&objectids, event->objectid);
1240 	}
1241 
1242 	if (0 != objectids.values_num)
1243 	{
1244 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1245 				"select dserviceid"
1246 				" from dservices"
1247 				"%s dcheckid=" ZBX_FS_UI64
1248 					" and",
1249 				operation_where,
1250 				condition_value);
1251 
1252 		zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1253 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1254 				objectids.values_num);
1255 
1256 		result = DBselect("%s", sql);
1257 
1258 		while (NULL != (row = DBfetch(result)))
1259 		{
1260 			zbx_uint64_t	objectid;
1261 
1262 			ZBX_STR2UINT64(objectid, row[0]);
1263 			add_condition_match(esc_events, condition, objectid, object);
1264 		}
1265 		DBfree_result(result);
1266 	}
1267 
1268 	zbx_vector_uint64_destroy(&objectids);
1269 	zbx_free(sql);
1270 
1271 	return SUCCEED;
1272 }
1273 
1274 /******************************************************************************
1275  *                                                                            *
1276  * Function: check_dobject_condition                                          *
1277  *                                                                            *
1278  * Purpose: check discovery object condition                                  *
1279  *                                                                            *
1280  * Parameters: esc_events - [IN] events to check                              *
1281  *             condition  - [IN/OUT] condition for matching, outputs          *
1282  *                                   event ids that match condition           *
1283  *                                                                            *
1284  * Return value: SUCCEED - supported operator                                 *
1285  *               NOTSUPPORTED - not supported operator                        *
1286  *                                                                            *
1287  ******************************************************************************/
check_dobject_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1288 static int	check_dobject_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1289 {
1290 	int	i, condition_value_i = atoi(condition->value);
1291 
1292 	if (CONDITION_OPERATOR_EQUAL != condition->op)
1293 		return NOTSUPPORTED;
1294 
1295 	for (i = 0; i < esc_events->values_num; i++)
1296 	{
1297 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
1298 
1299 		if (event->object == condition_value_i)
1300 			zbx_vector_uint64_append(&condition->eventids, event->eventid);
1301 	}
1302 
1303 	return SUCCEED;
1304 }
1305 
1306 /******************************************************************************
1307  *                                                                            *
1308  * Function: check_proxy_condition                                            *
1309  *                                                                            *
1310  * Purpose: check proxy condition for discovery event                         *
1311  *                                                                            *
1312  * Parameters: esc_events - [IN] events to check                              *
1313  *             condition  - [IN/OUT] condition for matching, outputs          *
1314  *                                   event ids that match condition           *
1315  *                                                                            *
1316  * Return value: SUCCEED - supported operator                                 *
1317  *               NOTSUPPORTED - not supported operator                        *
1318  *                                                                            *
1319  ******************************************************************************/
check_proxy_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1320 static int	check_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1321 {
1322 	char			*sql = NULL, *operation_and;
1323 	size_t			sql_alloc = 0, i;
1324 	DB_RESULT		result;
1325 	DB_ROW			row;
1326 	int			objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1327 	zbx_vector_uint64_t	objectids[2];
1328 	zbx_uint64_t		condition_value;
1329 
1330 	if (CONDITION_OPERATOR_EQUAL == condition->op)
1331 		operation_and = " and";
1332 	else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
1333 		operation_and = " and not";
1334 	else
1335 		return NOTSUPPORTED;
1336 
1337 	ZBX_STR2UINT64(condition_value, condition->value);
1338 
1339 	zbx_vector_uint64_create(&objectids[0]);
1340 	zbx_vector_uint64_create(&objectids[1]);
1341 
1342 	get_object_ids_discovery(esc_events, objectids);
1343 
1344 	for (i = 0; i < (int)ARRSIZE(objects); i++)
1345 	{
1346 		size_t	sql_offset = 0;
1347 
1348 		if (0 == objectids[i].values_num)
1349 			continue;
1350 
1351 		if (EVENT_OBJECT_DHOST == objects[i])
1352 		{
1353 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1354 					"select h.dhostid"
1355 					" from drules r,dhosts h"
1356 					" where r.druleid=h.druleid"
1357 						"%s r.proxy_hostid=" ZBX_FS_UI64
1358 						" and",
1359 					operation_and,
1360 					condition_value);
1361 
1362 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "h.dhostid", objectids[i].values,
1363 					objectids[i].values_num);
1364 		}
1365 		else	/* EVENT_OBJECT_DSERVICE */
1366 		{
1367 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1368 					"select s.dserviceid"
1369 					" from drules r,dhosts h,dservices s"
1370 					" where r.druleid=h.druleid"
1371 						" and h.dhostid=s.dhostid"
1372 						"%s r.proxy_hostid=" ZBX_FS_UI64
1373 						" and",
1374 					operation_and,
1375 					condition_value);
1376 
1377 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.dserviceid",
1378 					objectids[i].values, objectids[i].values_num);
1379 		}
1380 
1381 		result = DBselect("%s", sql);
1382 
1383 		while (NULL != (row = DBfetch(result)))
1384 		{
1385 			zbx_uint64_t	objectid;
1386 
1387 			ZBX_STR2UINT64(objectid, row[0]);
1388 			add_condition_match(esc_events, condition, objectid, objects[i]);
1389 		}
1390 		DBfree_result(result);
1391 	}
1392 
1393 	zbx_vector_uint64_destroy(&objectids[0]);
1394 	zbx_vector_uint64_destroy(&objectids[1]);
1395 	zbx_free(sql);
1396 
1397 	return SUCCEED;
1398 }
1399 
1400 /******************************************************************************
1401  *                                                                            *
1402  * Function: check_dvalue_condition                                           *
1403  *                                                                            *
1404  * Purpose: check discovery value condition                                   *
1405  *                                                                            *
1406  * Parameters: esc_events - [IN] events to check                              *
1407  *             condition  - [IN/OUT] condition for matching, outputs          *
1408  *                                   event ids that match condition           *
1409  *                                                                            *
1410  * Return value: SUCCEED - supported operator                                 *
1411  *               NOTSUPPORTED - not supported operator                        *
1412  *                                                                            *
1413  ******************************************************************************/
check_dvalue_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1414 static int	check_dvalue_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1415 {
1416 	char			*sql = NULL;
1417 	size_t			sql_alloc = 0, sql_offset = 0;
1418 	DB_RESULT		result;
1419 	DB_ROW			row;
1420 	int			object = EVENT_OBJECT_DSERVICE;
1421 	zbx_vector_uint64_t	objectids;
1422 	int			i;
1423 
1424 	switch (condition->op)
1425 	{
1426 		case CONDITION_OPERATOR_EQUAL:
1427 		case CONDITION_OPERATOR_NOT_EQUAL:
1428 		case CONDITION_OPERATOR_MORE_EQUAL:
1429 		case CONDITION_OPERATOR_LESS_EQUAL:
1430 		case CONDITION_OPERATOR_LIKE:
1431 		case CONDITION_OPERATOR_NOT_LIKE:
1432 			break;
1433 		default:
1434 			return NOTSUPPORTED;
1435 	}
1436 
1437 	zbx_vector_uint64_create(&objectids);
1438 
1439 	for (i = 0; i < esc_events->values_num; i++)
1440 	{
1441 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
1442 
1443 		if (object == event->object)
1444 			zbx_vector_uint64_append(&objectids, event->objectid);
1445 	}
1446 
1447 	if (0 != objectids.values_num)
1448 	{
1449 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1450 					"select dserviceid,value"
1451 					" from dservices"
1452 					" where");
1453 
1454 		zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1455 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1456 				objectids.values_num);
1457 
1458 		result = DBselect("%s", sql);
1459 
1460 		while (NULL != (row = DBfetch(result)))
1461 		{
1462 			zbx_uint64_t	objectid;
1463 
1464 			ZBX_STR2UINT64(objectid, row[0]);
1465 
1466 			switch (condition->op)
1467 			{
1468 				case CONDITION_OPERATOR_EQUAL:
1469 					if (0 == strcmp(condition->value, row[1]))
1470 						add_condition_match(esc_events, condition, objectid, object);
1471 					break;
1472 				case CONDITION_OPERATOR_NOT_EQUAL:
1473 					if (0 != strcmp(condition->value, row[1]))
1474 						add_condition_match(esc_events, condition, objectid, object);
1475 					break;
1476 				case CONDITION_OPERATOR_MORE_EQUAL:
1477 					if (0 <= strcmp(row[1], condition->value))
1478 						add_condition_match(esc_events, condition, objectid, object);
1479 					break;
1480 				case CONDITION_OPERATOR_LESS_EQUAL:
1481 					if (0 >= strcmp(row[1], condition->value))
1482 						add_condition_match(esc_events, condition, objectid, object);
1483 					break;
1484 				case CONDITION_OPERATOR_LIKE:
1485 					if (NULL != strstr(row[1], condition->value))
1486 						add_condition_match(esc_events, condition, objectid, object);
1487 					break;
1488 				case CONDITION_OPERATOR_NOT_LIKE:
1489 					if (NULL == strstr(row[1], condition->value))
1490 						add_condition_match(esc_events, condition, objectid, object);
1491 					break;
1492 			}
1493 		}
1494 		DBfree_result(result);
1495 	}
1496 
1497 	zbx_vector_uint64_destroy(&objectids);
1498 	zbx_free(sql);
1499 
1500 	return SUCCEED;
1501 }
1502 
1503 /******************************************************************************
1504  *                                                                            *
1505  * Function: check_dhost_ip_condition                                         *
1506  *                                                                            *
1507  * Purpose: check host ip condition for discovery event                       *
1508  *                                                                            *
1509  * Parameters: esc_events - [IN] events to check                              *
1510  *             condition  - [IN/OUT] condition for matching, outputs          *
1511  *                                   event ids that match condition           *
1512  *                                                                            *
1513  * Return value: SUCCEED - supported operator                                 *
1514  *               NOTSUPPORTED - not supported operator                        *
1515  *                                                                            *
1516  ******************************************************************************/
check_dhost_ip_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1517 static int	check_dhost_ip_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1518 {
1519 	char			*sql = NULL;
1520 	size_t			sql_alloc = 0, i;
1521 	DB_RESULT		result;
1522 	DB_ROW			row;
1523 	int			objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1524 	zbx_vector_uint64_t	objectids[2];
1525 	zbx_uint64_t		condition_value;
1526 
1527 	if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1528 		return NOTSUPPORTED;
1529 
1530 	ZBX_STR2UINT64(condition_value, condition->value);
1531 
1532 	zbx_vector_uint64_create(&objectids[0]);
1533 	zbx_vector_uint64_create(&objectids[1]);
1534 
1535 	get_object_ids_discovery(esc_events, objectids);
1536 
1537 	for (i = 0; i < (int)ARRSIZE(objects); i++)
1538 	{
1539 		size_t	sql_offset = 0;
1540 
1541 		if (0 == objectids[i].values_num)
1542 			continue;
1543 
1544 		if (EVENT_OBJECT_DHOST == objects[i])
1545 		{
1546 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1547 					"select distinct dhostid,ip"
1548 					" from dservices"
1549 					" where");
1550 
1551 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid", objectids[i].values,
1552 					objectids[i].values_num);
1553 		}
1554 		else	/* EVENT_OBJECT_DSERVICE */
1555 		{
1556 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1557 					"select distinct dserviceid,ip"
1558 					" from dservices"
1559 					" where");
1560 
1561 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid",
1562 					objectids[i].values, objectids[i].values_num);
1563 		}
1564 
1565 		result = DBselect("%s", sql);
1566 
1567 		while (NULL != (row = DBfetch(result)))
1568 		{
1569 			zbx_uint64_t	objectid;
1570 
1571 			ZBX_STR2UINT64(objectid, row[0]);
1572 			switch (condition->op)
1573 			{
1574 				case CONDITION_OPERATOR_EQUAL:
1575 					if (SUCCEED == ip_in_list(condition->value, row[1]))
1576 						add_condition_match(esc_events, condition, objectid, objects[i]);
1577 					break;
1578 				case CONDITION_OPERATOR_NOT_EQUAL:
1579 					if (SUCCEED != ip_in_list(condition->value, row[1]))
1580 						add_condition_match(esc_events, condition, objectid, objects[i]);
1581 					break;
1582 			}
1583 		}
1584 		DBfree_result(result);
1585 	}
1586 
1587 	zbx_vector_uint64_destroy(&objectids[0]);
1588 	zbx_vector_uint64_destroy(&objectids[1]);
1589 	zbx_free(sql);
1590 
1591 	return SUCCEED;
1592 }
1593 
1594 /******************************************************************************
1595  *                                                                            *
1596  * Function: check_dservice_type_condition                                    *
1597  *                                                                            *
1598  * Purpose: check service type condition for discovery event                  *
1599  *                                                                            *
1600  * Parameters: esc_events - [IN] events to check                              *
1601  *             condition  - [IN/OUT] condition for matching, outputs          *
1602  *                                   event ids that match condition           *
1603  *                                                                            *
1604  * Return value: SUCCEED - supported operator                                 *
1605  *               NOTSUPPORTED - not supported operator                        *
1606  *                                                                            *
1607  ******************************************************************************/
check_dservice_type_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1608 static int	check_dservice_type_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1609 {
1610 	char			*sql = NULL;
1611 	size_t			sql_alloc = 0, sql_offset = 0;
1612 	DB_RESULT		result;
1613 	DB_ROW			row;
1614 	int			object = EVENT_OBJECT_DSERVICE;
1615 	zbx_vector_uint64_t	objectids;
1616 	int			i, condition_value_i;
1617 
1618 	if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1619 		return NOTSUPPORTED;
1620 
1621 	condition_value_i = atoi(condition->value);
1622 
1623 	zbx_vector_uint64_create(&objectids);
1624 
1625 	for (i = 0; i < esc_events->values_num; i++)
1626 	{
1627 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
1628 
1629 		if (object == event->object)
1630 			zbx_vector_uint64_append(&objectids, event->objectid);
1631 	}
1632 
1633 	if (0 != objectids.values_num)
1634 	{
1635 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1636 				"select ds.dserviceid,dc.type"
1637 				" from dservices ds,dchecks dc"
1638 				" where ds.dcheckid=dc.dcheckid"
1639 					" and");
1640 
1641 		zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1642 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ds.dserviceid", objectids.values,
1643 				objectids.values_num);
1644 
1645 		result = DBselect("%s", sql);
1646 
1647 		while (NULL != (row = DBfetch(result)))
1648 		{
1649 			zbx_uint64_t	objectid;
1650 			int		tmp_int;
1651 
1652 			ZBX_STR2UINT64(objectid, row[0]);
1653 			tmp_int = atoi(row[1]);
1654 
1655 			switch (condition->op)
1656 			{
1657 				case CONDITION_OPERATOR_EQUAL:
1658 					if (condition_value_i == tmp_int)
1659 						add_condition_match(esc_events, condition, objectid, object);
1660 					break;
1661 				case CONDITION_OPERATOR_NOT_EQUAL:
1662 					if (condition_value_i != tmp_int)
1663 						add_condition_match(esc_events, condition, objectid, object);
1664 					break;
1665 			}
1666 		}
1667 		DBfree_result(result);
1668 	}
1669 
1670 	zbx_vector_uint64_destroy(&objectids);
1671 	zbx_free(sql);
1672 
1673 	return SUCCEED;
1674 }
1675 
1676 /******************************************************************************
1677  *                                                                            *
1678  * Function: check_dstatus_condition                                          *
1679  *                                                                            *
1680  * Purpose: check discovery status condition                                  *
1681  *                                                                            *
1682  * Parameters: esc_events - [IN] events to check                              *
1683  *             condition  - [IN/OUT] condition for matching, outputs          *
1684  *                                   event ids that match condition           *
1685  *                                                                            *
1686  * Return value: SUCCEED - supported operator                                 *
1687  *               NOTSUPPORTED - not supported operator                        *
1688  *                                                                            *
1689  ******************************************************************************/
check_dstatus_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1690 static int	check_dstatus_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1691 {
1692 	int	i, condition_value_i = atoi(condition->value);
1693 
1694 	for (i = 0; i < esc_events->values_num; i++)
1695 	{
1696 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
1697 
1698 		switch (condition->op)
1699 		{
1700 			case CONDITION_OPERATOR_EQUAL:
1701 				if (condition_value_i == event->value)
1702 					zbx_vector_uint64_append(&condition->eventids, event->eventid);
1703 				break;
1704 			case CONDITION_OPERATOR_NOT_EQUAL:
1705 				if (condition_value_i != event->value)
1706 					zbx_vector_uint64_append(&condition->eventids, event->eventid);
1707 				break;
1708 			default:
1709 				return NOTSUPPORTED;
1710 		}
1711 	}
1712 
1713 	return SUCCEED;
1714 }
1715 
1716 /******************************************************************************
1717  *                                                                            *
1718  * Function: check_duptime_condition                                          *
1719  *                                                                            *
1720  * Purpose: check uptime condition for discovery                              *
1721  *                                                                            *
1722  * Parameters: esc_events - [IN] events to check                              *
1723  *             condition  - [IN/OUT] condition for matching, outputs          *
1724  *                                   event ids that match condition           *
1725  *                                                                            *
1726  * Return value: SUCCEED - supported operator                                 *
1727  *               NOTSUPPORTED - not supported operator                        *
1728  *                                                                            *
1729  ******************************************************************************/
check_duptime_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1730 static int	check_duptime_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1731 {
1732 	char			*sql = NULL;
1733 	size_t			sql_alloc = 0, i;
1734 	DB_RESULT		result;
1735 	DB_ROW			row;
1736 	int			objects[2] = {EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE};
1737 	zbx_vector_uint64_t	objectids[2];
1738 	int			condition_value_i;
1739 
1740 	if (CONDITION_OPERATOR_LESS_EQUAL != condition->op && CONDITION_OPERATOR_MORE_EQUAL != condition->op)
1741 		return NOTSUPPORTED;
1742 
1743 	condition_value_i = atoi(condition->value);
1744 
1745 	zbx_vector_uint64_create(&objectids[0]);
1746 	zbx_vector_uint64_create(&objectids[1]);
1747 
1748 	get_object_ids_discovery(esc_events, objectids);
1749 
1750 	for (i = 0; i < (int)ARRSIZE(objects); i++)
1751 	{
1752 		size_t	sql_offset = 0;
1753 
1754 		if (0 == objectids[i].values_num)
1755 			continue;
1756 
1757 		if (EVENT_OBJECT_DHOST == objects[i])
1758 		{
1759 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1760 					"select dhostid,status,lastup,lastdown"
1761 					" from dhosts"
1762 					" where");
1763 
1764 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dhostid",
1765 					objectids[i].values, objectids[i].values_num);
1766 		}
1767 		else	/* EVENT_OBJECT_DSERVICE */
1768 		{
1769 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1770 					"select dserviceid,status,lastup,lastdown"
1771 					" from dservices"
1772 					" where");
1773 
1774 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid",
1775 					objectids[i].values, objectids[i].values_num);
1776 		}
1777 
1778 		result = DBselect("%s", sql);
1779 
1780 		while (NULL != (row = DBfetch(result)))
1781 		{
1782 			zbx_uint64_t	objectid;
1783 			int		now, tmp_int;
1784 
1785 			ZBX_STR2UINT64(objectid, row[0]);
1786 
1787 			now = time(NULL);
1788 			tmp_int = DOBJECT_STATUS_UP == atoi(row[1]) ? atoi(row[2]) : atoi(row[3]);
1789 
1790 			switch (condition->op)
1791 			{
1792 				case CONDITION_OPERATOR_LESS_EQUAL:
1793 					if (0 != tmp_int && (now - tmp_int) <= condition_value_i)
1794 						add_condition_match(esc_events, condition, objectid, objects[i]);
1795 					break;
1796 				case CONDITION_OPERATOR_MORE_EQUAL:
1797 					if (0 != tmp_int && (now - tmp_int) >= condition_value_i)
1798 						add_condition_match(esc_events, condition, objectid, objects[i]);
1799 					break;
1800 			}
1801 		}
1802 		DBfree_result(result);
1803 	}
1804 
1805 	zbx_vector_uint64_destroy(&objectids[0]);
1806 	zbx_vector_uint64_destroy(&objectids[1]);
1807 	zbx_free(sql);
1808 
1809 	return SUCCEED;
1810 }
1811 
1812 /******************************************************************************
1813  *                                                                            *
1814  * Function: check_dservice_port_condition                                    *
1815  *                                                                            *
1816  * Purpose: check service port condition for discovery                        *
1817  *                                                                            *
1818  * Parameters: esc_events - [IN] events to check                              *
1819  *             condition  - [IN/OUT] condition for matching, outputs          *
1820  *                                   event ids that match condition           *
1821  *                                                                            *
1822  * Return value: SUCCEED - supported operator                                 *
1823  *               NOTSUPPORTED - not supported operator                        *
1824  *                                                                            *
1825  ******************************************************************************/
check_dservice_port_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1826 static int	check_dservice_port_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1827 {
1828 	char			*sql = NULL;
1829 	size_t			sql_alloc = 0, sql_offset = 0;
1830 	DB_RESULT		result;
1831 	DB_ROW			row;
1832 	int			object = EVENT_OBJECT_DSERVICE;
1833 	zbx_vector_uint64_t	objectids;
1834 	int			i;
1835 
1836 	if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
1837 		return NOTSUPPORTED;
1838 
1839 	zbx_vector_uint64_create(&objectids);
1840 
1841 	for (i = 0; i < esc_events->values_num; i++)
1842 	{
1843 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
1844 
1845 		if (object == event->object)
1846 			zbx_vector_uint64_append(&objectids, event->objectid);
1847 	}
1848 
1849 	if (0 != objectids.values_num)
1850 	{
1851 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1852 				"select dserviceid,port"
1853 				" from dservices"
1854 				" where");
1855 
1856 		zbx_vector_uint64_uniq(&objectids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1857 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "dserviceid", objectids.values,
1858 				objectids.values_num);
1859 
1860 		result = DBselect("%s", sql);
1861 
1862 		while (NULL != (row = DBfetch(result)))
1863 		{
1864 			zbx_uint64_t	objectid;
1865 
1866 			ZBX_STR2UINT64(objectid, row[0]);
1867 			switch (condition->op)
1868 			{
1869 				case CONDITION_OPERATOR_EQUAL:
1870 					if (SUCCEED == int_in_list(condition->value, atoi(row[1])))
1871 						add_condition_match(esc_events, condition, objectid, object);
1872 					break;
1873 				case CONDITION_OPERATOR_NOT_EQUAL:
1874 					if (SUCCEED != int_in_list(condition->value, atoi(row[1])))
1875 						add_condition_match(esc_events, condition, objectid, object);
1876 					break;
1877 			}
1878 		}
1879 		DBfree_result(result);
1880 	}
1881 
1882 	zbx_vector_uint64_destroy(&objectids);
1883 	zbx_free(sql);
1884 
1885 	return SUCCEED;
1886 }
1887 
1888 /******************************************************************************
1889  *                                                                            *
1890  * Function: check_discovery_condition                                        *
1891  *                                                                            *
1892  * Purpose: check if event matches single condition                           *
1893  *                                                                            *
1894  * Parameters: event - discovery event to check                               *
1895  *                                 (event->source == EVENT_SOURCE_DISCOVERY)  *
1896  *             condition - condition for matching                             *
1897  *                                                                            *
1898  * Return value: SUCCEED - matches, FAIL - otherwise                          *
1899  *                                                                            *
1900  * Author: Alexei Vladishev                                                   *
1901  *                                                                            *
1902  ******************************************************************************/
check_discovery_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1903 static void	check_discovery_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1904 {
1905 	int	ret;
1906 
1907 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1908 
1909 	switch (condition->conditiontype)
1910 	{
1911 		case CONDITION_TYPE_DRULE:
1912 			ret = check_drule_condition(esc_events, condition);
1913 			break;
1914 		case CONDITION_TYPE_DCHECK:
1915 			ret = check_dcheck_condition(esc_events, condition);
1916 			break;
1917 		case CONDITION_TYPE_DOBJECT:
1918 			ret = check_dobject_condition(esc_events, condition);
1919 			break;
1920 		case CONDITION_TYPE_PROXY:
1921 			ret = check_proxy_condition(esc_events, condition);
1922 			break;
1923 		case CONDITION_TYPE_DVALUE:
1924 			ret = check_dvalue_condition(esc_events, condition);
1925 			break;
1926 		case CONDITION_TYPE_DHOST_IP:
1927 			ret = check_dhost_ip_condition(esc_events, condition);
1928 			break;
1929 		case CONDITION_TYPE_DSERVICE_TYPE:
1930 			ret = check_dservice_type_condition(esc_events, condition);
1931 			break;
1932 		case CONDITION_TYPE_DSTATUS:
1933 			ret = check_dstatus_condition(esc_events, condition);
1934 			break;
1935 		case CONDITION_TYPE_DUPTIME:
1936 			ret = check_duptime_condition(esc_events, condition);
1937 			break;
1938 		case CONDITION_TYPE_DSERVICE_PORT:
1939 			ret = check_dservice_port_condition(esc_events, condition);
1940 			break;
1941 		default:
1942 			ret = FAIL;
1943 			zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
1944 					(int)condition->conditiontype, condition->conditionid);
1945 	}
1946 
1947 	if (NOTSUPPORTED == ret)
1948 	{
1949 		zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
1950 				(int)condition->op, condition->conditionid);
1951 	}
1952 
1953 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
1954 }
1955 
1956 /******************************************************************************
1957  *                                                                            *
1958  * Function: check_hostname_metadata_condition                                *
1959  *                                                                            *
1960  * Purpose: check metadata or host condition for auto registration            *
1961  *                                                                            *
1962  * Parameters: esc_events - [IN] events to check                              *
1963  *             condition  - [IN/OUT] condition for matching, outputs          *
1964  *                                   event ids that match condition           *
1965  *                                                                            *
1966  * Return value: SUCCEED - supported operator                                 *
1967  *               NOTSUPPORTED - not supported operator                        *
1968  *                                                                            *
1969  ******************************************************************************/
check_hostname_metadata_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)1970 static int	check_hostname_metadata_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
1971 {
1972 	char			*sql = NULL;
1973 	size_t			sql_alloc = 0, sql_offset = 0;
1974 	DB_RESULT		result;
1975 	DB_ROW			row;
1976 	int			object = EVENT_OBJECT_ZABBIX_ACTIVE;
1977 	zbx_vector_uint64_t	objectids;
1978 	const char		*condition_field;
1979 
1980 	switch(condition->op)
1981 	{
1982 		case CONDITION_OPERATOR_LIKE:
1983 		case CONDITION_OPERATOR_NOT_LIKE:
1984 		case CONDITION_OPERATOR_REGEXP:
1985 		case CONDITION_OPERATOR_NOT_REGEXP:
1986 			break;
1987 		default:
1988 			return NOTSUPPORTED;
1989 	}
1990 
1991 	if (CONDITION_TYPE_HOST_NAME == condition->conditiontype)
1992 		condition_field = "host";
1993 	else
1994 		condition_field = "host_metadata";
1995 
1996 	zbx_vector_uint64_create(&objectids);
1997 	get_object_ids(esc_events, &objectids);
1998 
1999 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2000 			"select autoreg_hostid,%s"
2001 			" from autoreg_host"
2002 			" where",
2003 			condition_field);
2004 
2005 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "autoreg_hostid", objectids.values, objectids.values_num);
2006 
2007 	result = DBselect("%s", sql);
2008 
2009 	while (NULL != (row = DBfetch(result)))
2010 	{
2011 		zbx_uint64_t	objectid;
2012 
2013 		ZBX_STR2UINT64(objectid, row[0]);
2014 
2015 		switch (condition->op)
2016 		{
2017 			case CONDITION_OPERATOR_LIKE:
2018 				if (NULL != strstr(row[1], condition->value))
2019 					add_condition_match(esc_events, condition, objectid, object);
2020 				break;
2021 			case CONDITION_OPERATOR_NOT_LIKE:
2022 				if (NULL == strstr(row[1], condition->value))
2023 					add_condition_match(esc_events, condition, objectid, object);
2024 				break;
2025 			case CONDITION_OPERATOR_REGEXP:
2026 				if (NULL != zbx_regexp_match(row[1], condition->value, NULL))
2027 					add_condition_match(esc_events, condition, objectid, object);
2028 				break;
2029 			case CONDITION_OPERATOR_NOT_REGEXP:
2030 				if (NULL == zbx_regexp_match(row[1], condition->value, NULL))
2031 					add_condition_match(esc_events, condition, objectid, object);
2032 				break;
2033 		}
2034 	}
2035 	DBfree_result(result);
2036 
2037 	zbx_vector_uint64_destroy(&objectids);
2038 	zbx_free(sql);
2039 
2040 	return SUCCEED;
2041 }
2042 
2043 /******************************************************************************
2044  *                                                                            *
2045  * Function: check_areg_proxy_condition                                       *
2046  *                                                                            *
2047  * Purpose: check proxy condition for auto registration                       *
2048  *                                                                            *
2049  * Parameters: esc_events - [IN] events to check                              *
2050  *             condition  - [IN/OUT] condition for matching, outputs          *
2051  *                                   event ids that match condition           *
2052  *                                                                            *
2053  * Return value: SUCCEED - supported operator                                 *
2054  *               NOTSUPPORTED - not supported operator                        *
2055  *                                                                            *
2056  ******************************************************************************/
check_areg_proxy_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2057 static int	check_areg_proxy_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2058 {
2059 	char			*sql = NULL;
2060 	size_t			sql_alloc = 0, sql_offset = 0;
2061 	DB_RESULT		result;
2062 	DB_ROW			row;
2063 	int			object = EVENT_OBJECT_ZABBIX_ACTIVE;
2064 	zbx_vector_uint64_t	objectids;
2065 	zbx_uint64_t		condition_value;
2066 
2067 	ZBX_STR2UINT64(condition_value, condition->value);
2068 
2069 	if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
2070 		return NOTSUPPORTED;
2071 
2072 	zbx_vector_uint64_create(&objectids);
2073 	get_object_ids(esc_events, &objectids);
2074 
2075 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2076 			"select autoreg_hostid,proxy_hostid"
2077 			" from autoreg_host"
2078 			" where");
2079 
2080 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "autoreg_hostid",
2081 			objectids.values, objectids.values_num);
2082 
2083 	result = DBselect("%s", sql);
2084 
2085 	while (NULL != (row = DBfetch(result)))
2086 	{
2087 		zbx_uint64_t	id;
2088 		zbx_uint64_t	objectid;
2089 
2090 		ZBX_STR2UINT64(objectid, row[0]);
2091 		ZBX_DBROW2UINT64(id, row[1]);
2092 
2093 		switch (condition->op)
2094 		{
2095 			case CONDITION_OPERATOR_EQUAL:
2096 				if (id == condition_value)
2097 					add_condition_match(esc_events, condition, objectid, object);
2098 				break;
2099 			case CONDITION_OPERATOR_NOT_EQUAL:
2100 				if (id != condition_value)
2101 					add_condition_match(esc_events, condition, objectid, object);
2102 				break;
2103 		}
2104 	}
2105 	DBfree_result(result);
2106 
2107 	zbx_vector_uint64_destroy(&objectids);
2108 	zbx_free(sql);
2109 
2110 	return SUCCEED;
2111 }
2112 
2113 /******************************************************************************
2114  *                                                                            *
2115  * Function: check_autoregistration_condition                                 *
2116  *                                                                            *
2117  * Purpose: check if event matches single condition                           *
2118  *                                                                            *
2119  * Parameters: event - autoregistration event to check                        *
2120  *                         (event->source == EVENT_SOURCE_AUTOREGISTRATION)   *
2121  *             condition - condition for matching                             *
2122  *                                                                            *
2123  * Return value: SUCCEED - matches, FAIL - otherwise                          *
2124  *                                                                            *
2125  * Author: Alexei Vladishev                                                   *
2126  *                                                                            *
2127  ******************************************************************************/
check_autoregistration_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2128 static void	check_autoregistration_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2129 {
2130 	const char	*__function_name = "check_auto_registration_condition";
2131 	int		ret;
2132 
2133 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2134 
2135 	switch (condition->conditiontype)
2136 	{
2137 		case CONDITION_TYPE_HOST_NAME:
2138 		case CONDITION_TYPE_HOST_METADATA:
2139 			ret = check_hostname_metadata_condition(esc_events, condition);
2140 			break;
2141 		case CONDITION_TYPE_PROXY:
2142 			ret = check_areg_proxy_condition(esc_events, condition);
2143 			break;
2144 		default:
2145 			zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
2146 					(int)condition->conditiontype, condition->conditionid);
2147 			ret = FAIL;
2148 	}
2149 
2150 	if (NOTSUPPORTED == ret)
2151 	{
2152 		zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
2153 				(int)condition->op, condition->conditionid);
2154 	}
2155 
2156 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2157 }
2158 
2159 /******************************************************************************
2160  *                                                                            *
2161  * Function: is_supported_event_object                                        *
2162  *                                                                            *
2163  * Purpose: not all event objects are supported for internal events           *
2164  *                                                                            *
2165  * Parameters: events     - [IN]  events to check                             *
2166  *                                                                            *
2167  * Return value: SUCCEED - supported                                          *
2168  *               FAIL - not supported                                         *
2169  *                                                                            *
2170  ******************************************************************************/
is_supported_event_object(const DB_EVENT * event)2171 static int	is_supported_event_object(const DB_EVENT *event)
2172 {
2173 	return (EVENT_OBJECT_TRIGGER == event->object || EVENT_OBJECT_ITEM == event->object ||
2174 					EVENT_OBJECT_LLDRULE == event->object) ? SUCCEED : FAIL;
2175 }
2176 
2177 /******************************************************************************
2178  *                                                                            *
2179  * Function: check_intern_event_type_condition                                *
2180  *                                                                            *
2181  * Purpose: check event type condition for internal events                    *
2182  *                                                                            *
2183  * Parameters: esc_events - [IN] events to check                              *
2184  *             condition  - [IN/OUT] condition for matching, outputs          *
2185  *                                   event ids that match condition           *
2186  *                                                                            *
2187  * Return value: SUCCEED - supported operator                                 *
2188  *               NOTSUPPORTED - not supported operator                        *
2189  *                                                                            *
2190  ******************************************************************************/
check_intern_event_type_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2191 static int	check_intern_event_type_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2192 {
2193 	int		i;
2194 	zbx_uint64_t	condition_value;
2195 
2196 	condition_value = atoi(condition->value);
2197 
2198 	for (i = 0; i < esc_events->values_num; i++)
2199 	{
2200 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
2201 
2202 		if (FAIL == is_supported_event_object(event))
2203 		{
2204 			zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d] for condition id [" ZBX_FS_UI64 "]",
2205 					event->object, condition->conditionid);
2206 			continue;
2207 		}
2208 
2209 		switch (condition_value)
2210 		{
2211 			case EVENT_TYPE_ITEM_NOTSUPPORTED:
2212 				if (EVENT_OBJECT_ITEM == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
2213 					zbx_vector_uint64_append(&condition->eventids, event->eventid);
2214 				break;
2215 			case EVENT_TYPE_TRIGGER_UNKNOWN:
2216 				if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_STATE_UNKNOWN == event->value)
2217 					zbx_vector_uint64_append(&condition->eventids, event->eventid);
2218 				break;
2219 			case EVENT_TYPE_LLDRULE_NOTSUPPORTED:
2220 				if (EVENT_OBJECT_LLDRULE == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
2221 					zbx_vector_uint64_append(&condition->eventids, event->eventid);
2222 				break;
2223 			default:
2224 				return NOTSUPPORTED;
2225 		}
2226 	}
2227 
2228 	return SUCCEED;
2229 }
2230 
2231 /******************************************************************************
2232  *                                                                            *
2233  * Function: get_object_ids_internal                                          *
2234  *                                                                            *
2235  * Purpose: get objectids of escalation internal events                       *
2236  *                                                                            *
2237  * Parameters: esc_events  - [IN]  events to check                            *
2238  *             objectids   - [OUT] event objectids to be used in condition    *
2239  *                                 allocation 2 vectors where first one is    *
2240  *                                 trigger object ids, second is rest         *
2241  *             objects     - [IN] the array of event objects                  *
2242  *             objects_num - [IN] the number of objects in objects array      *
2243  *                                                                            *
2244  ******************************************************************************/
get_object_ids_internal(const zbx_vector_ptr_t * esc_events,zbx_vector_uint64_t * objectids,const int * objects,const int objects_num)2245 static void	get_object_ids_internal(const zbx_vector_ptr_t *esc_events, zbx_vector_uint64_t *objectids,
2246 		const int *objects, const int objects_num)
2247 {
2248 	int	i, j;
2249 
2250 	for (i = 0; i < esc_events->values_num; i++)
2251 	{
2252 		const DB_EVENT	*event = (DB_EVENT *)esc_events->values[i];
2253 
2254 		for (j = 0; j < objects_num; j++)
2255 		{
2256 			if (event->object == objects[j])
2257 			{
2258 				zbx_vector_uint64_append(&objectids[j], event->objectid);
2259 				break;
2260 			}
2261 		}
2262 
2263 		if (j == objects_num)
2264 			zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d]", event->object);
2265 	}
2266 
2267 	for (i = 0; i < objects_num; i++)
2268 		zbx_vector_uint64_uniq(&objectids[i], ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2269 }
2270 
2271 /******************************************************************************
2272  *                                                                            *
2273  * Function: check_intern_host_group_condition                                *
2274  *                                                                            *
2275  * Purpose: check host group condition for internal events                    *
2276  *                                                                            *
2277  * Parameters: esc_events - [IN] events to check                              *
2278  *             condition  - [IN/OUT] condition for matching, outputs          *
2279  *                                   event ids that match condition           *
2280  *                                                                            *
2281  * Return value: SUCCEED - supported operator                                 *
2282  *               NOTSUPPORTED - not supported operator                        *
2283  *                                                                            *
2284  ******************************************************************************/
check_intern_host_group_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2285 static int	check_intern_host_group_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2286 {
2287 	char			*sql = NULL;
2288 	size_t			sql_alloc = 0, i;
2289 	DB_RESULT		result;
2290 	DB_ROW			row;
2291 	int			objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2292 	zbx_vector_uint64_t	objectids[3], groupids;
2293 	zbx_uint64_t		condition_value;
2294 
2295 	if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
2296 		return NOTSUPPORTED;
2297 
2298 	ZBX_STR2UINT64(condition_value, condition->value);
2299 
2300 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2301 		zbx_vector_uint64_create(&objectids[i]);
2302 
2303 	zbx_vector_uint64_create(&groupids);
2304 
2305 	get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2306 
2307 	zbx_dc_get_nested_hostgroupids(&condition_value, 1, &groupids);
2308 
2309 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2310 	{
2311 		size_t	sql_offset = 0;
2312 
2313 		if (0 == objectids[i].values_num)
2314 			continue;
2315 
2316 		if (EVENT_OBJECT_TRIGGER == objects[i])
2317 		{
2318 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2319 					"select distinct f.triggerid"
2320 					" from hosts_groups hg,hosts h,items i,functions f"
2321 					" where hg.hostid=h.hostid"
2322 						" and h.hostid=i.hostid"
2323 						" and i.itemid=f.itemid"
2324 						" and");
2325 
2326 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid", objectids[i].values,
2327 					objectids[i].values_num);
2328 		}
2329 		else	/* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2330 		{
2331 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2332 					"select distinct i.itemid"
2333 					" from hosts_groups hg,hosts h,items i"
2334 					" where hg.hostid=h.hostid"
2335 						" and h.hostid=i.hostid"
2336 						" and");
2337 
2338 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid",
2339 					objectids[i].values, objectids[i].values_num);
2340 		}
2341 
2342 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and");
2343 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.groupid", groupids.values,
2344 				groupids.values_num);
2345 
2346 		result = DBselect("%s", sql);
2347 
2348 		while (NULL != (row = DBfetch(result)))
2349 		{
2350 			zbx_uint64_t	objectid;
2351 
2352 			ZBX_STR2UINT64(objectid, row[0]);
2353 			if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2354 			{
2355 				int	index;
2356 
2357 				if (FAIL != (index = zbx_vector_uint64_search(&objectids[i], objectid,
2358 						ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2359 				{
2360 					zbx_vector_uint64_remove_noorder(&objectids[i], index);
2361 				}
2362 			}
2363 			else
2364 				add_condition_match(esc_events, condition, objectid, objects[i]);
2365 		}
2366 		DBfree_result(result);
2367 	}
2368 
2369 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2370 	{
2371 		if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2372 		{
2373 			int	j;
2374 
2375 			for (j = 0; j < objectids[i].values_num; j++)
2376 				add_condition_match(esc_events, condition, objectids[i].values[j], objects[i]);
2377 		}
2378 
2379 		zbx_vector_uint64_destroy(&objectids[i]);
2380 	}
2381 
2382 	zbx_vector_uint64_destroy(&groupids);
2383 	zbx_free(sql);
2384 
2385 	return SUCCEED;
2386 }
2387 
2388 /******************************************************************************
2389  *                                                                            *
2390  * Function: item_parents_sql_alloc                                           *
2391  *                                                                            *
2392  * Purpose: get parent id from item discovery                                 *
2393  *                                                                            *
2394  * Parameters: sql           [IN/OUT] - allocated sql query                   *
2395  *             sql_alloc     [IN/OUT] - how much bytes allocated              *
2396  *             objectids_tmp [IN/OUT] - uses to allocate query, removes       *
2397  *                                      duplicates                            *
2398  *                                                                            *
2399  ******************************************************************************/
item_parents_sql_alloc(char ** sql,size_t * sql_alloc,zbx_vector_uint64_t * objectids_tmp)2400 static void	item_parents_sql_alloc(char **sql, size_t *sql_alloc, zbx_vector_uint64_t *objectids_tmp)
2401 {
2402 	size_t	sql_offset = 0;
2403 
2404 	zbx_snprintf_alloc(sql, sql_alloc, &sql_offset,
2405 			"select i.itemid,id.parent_itemid"
2406 			" from item_discovery id,items i"
2407 			" where id.itemid=i.itemid"
2408 				" and i.flags=%d"
2409 				" and",
2410 			ZBX_FLAG_DISCOVERY_CREATED);
2411 
2412 	DBadd_condition_alloc(sql, sql_alloc, &sql_offset, "i.itemid",
2413 			objectids_tmp->values, objectids_tmp->values_num);
2414 }
2415 
2416 
2417 
2418 /******************************************************************************
2419  *                                                                            *
2420  * Function: check_intern_host_template_condition                             *
2421  *                                                                            *
2422  * Purpose: check host template condition for internal events                 *
2423  *                                                                            *
2424  * Parameters: esc_events - [IN] events to check                              *
2425  *             condition  - [IN/OUT] condition for matching, outputs          *
2426  *                                   event ids that match condition           *
2427  *                                                                            *
2428  * Return value: SUCCEED - supported operator                                 *
2429  *               NOTSUPPORTED - not supported operator                        *
2430  *                                                                            *
2431  ******************************************************************************/
check_intern_host_template_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2432 static int	check_intern_host_template_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2433 {
2434 	char				*sql = NULL;
2435 	size_t				sql_alloc = 0;
2436 	DB_RESULT			result;
2437 	DB_ROW				row;
2438 	zbx_uint64_t			condition_value;
2439 	int				i, j;
2440 	int				objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2441 	zbx_vector_uint64_t		objectids[3];
2442 	zbx_vector_uint64_pair_t	objectids_pair[3];
2443 
2444 	if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_NOT_EQUAL != condition->op)
2445 		return NOTSUPPORTED;
2446 
2447 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2448 	{
2449 		zbx_vector_uint64_create(&objectids[i]);
2450 		zbx_vector_uint64_pair_create(&objectids_pair[i]);
2451 	}
2452 
2453 	get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2454 
2455 	ZBX_STR2UINT64(condition_value, condition->value);
2456 
2457 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2458 	{
2459 		zbx_vector_uint64_t		*objectids_ptr = &objectids[i];
2460 		zbx_vector_uint64_pair_t	*objectids_pair_ptr = &objectids_pair[i];
2461 
2462 		if (0 == objectids_ptr->values_num)
2463 			continue;
2464 
2465 		objectids_to_pair(objectids_ptr, objectids_pair_ptr);
2466 
2467 		if (EVENT_OBJECT_TRIGGER == objects[i])
2468 			trigger_parents_sql_alloc(&sql, &sql_alloc, objectids_ptr);
2469 		else	/* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2470 			item_parents_sql_alloc(&sql, &sql_alloc, objectids_ptr);
2471 
2472 		result = DBselect("%s", sql);
2473 
2474 		while (NULL != (row = DBfetch(result)))
2475 		{
2476 			zbx_uint64_pair_t	pair;
2477 
2478 			ZBX_STR2UINT64(pair.first, row[0]);
2479 
2480 			if (FAIL != (j = zbx_vector_uint64_pair_search(objectids_pair_ptr, pair,
2481 					ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2482 			{
2483 				ZBX_STR2UINT64(objectids_pair_ptr->values[j].second, row[1]);
2484 			}
2485 		}
2486 		DBfree_result(result);
2487 
2488 		check_object_hierarchy(objects[i], esc_events, objectids_ptr, objectids_pair_ptr, condition, condition_value,
2489 				0 == i ?
2490 					"select distinct t.triggerid,t.templateid,i.hostid"
2491 						" from items i,functions f,triggers t"
2492 						" where i.itemid=f.itemid"
2493 							" and f.triggerid=t.templateid"
2494 							" and" :
2495 					"select distinct h.itemid,t.itemid,t.hostid"
2496 						" from items t,items h"
2497 						" where t.itemid=h.templateid"
2498 							" and",
2499 				0 == i ? "t.triggerid" : "h.itemid");
2500 	}
2501 
2502 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2503 	{
2504 		zbx_vector_uint64_destroy(&objectids[i]);
2505 		zbx_vector_uint64_pair_destroy(&objectids_pair[i]);
2506 	}
2507 
2508 	zbx_free(sql);
2509 
2510 	return SUCCEED;
2511 }
2512 
2513 /******************************************************************************
2514  *                                                                            *
2515  * Function: check_intern_host_condition                                      *
2516  *                                                                            *
2517  * Purpose: check host condition for internal events                          *
2518  *                                                                            *
2519  * Parameters: esc_events - [IN] events to check                              *
2520  *             condition  - [IN/OUT] condition for matching, outputs          *
2521  *                                   event ids that match condition           *
2522  *                                                                            *
2523  * Return value: SUCCEED - supported operator                                 *
2524  *               NOTSUPPORTED - not supported operator                        *
2525  *                                                                            *
2526  ******************************************************************************/
check_intern_host_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2527 static int	check_intern_host_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2528 {
2529 	char			*sql = NULL, *operation, *operation_item;
2530 	size_t			sql_alloc = 0, i;
2531 	DB_RESULT		result;
2532 	DB_ROW			row;
2533 	int			objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE};
2534 	zbx_vector_uint64_t	objectids[3];
2535 	zbx_uint64_t		condition_value;
2536 
2537 	if (CONDITION_OPERATOR_EQUAL == condition->op)
2538 	{
2539 		operation = " and";
2540 		operation_item = " where";
2541 	}
2542 	else if (CONDITION_OPERATOR_NOT_EQUAL == condition->op)
2543 	{
2544 		operation = " and not";
2545 		operation_item = " where not";
2546 	}
2547 	else
2548 		return NOTSUPPORTED;
2549 
2550 	ZBX_STR2UINT64(condition_value, condition->value);
2551 
2552 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2553 		zbx_vector_uint64_create(&objectids[i]);
2554 
2555 	get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2556 
2557 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2558 	{
2559 		size_t	sql_offset = 0;
2560 
2561 		if (0 == objectids[i].values_num)
2562 			continue;
2563 
2564 		if (EVENT_OBJECT_TRIGGER == objects[i])
2565 		{
2566 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2567 					"select distinct f.triggerid"
2568 					" from items i,functions f"
2569 					" where i.itemid=f.itemid"
2570 						"%s i.hostid=" ZBX_FS_UI64
2571 						" and",
2572 					operation,
2573 					condition_value);
2574 
2575 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "f.triggerid",
2576 					objectids[i].values, objectids[i].values_num);
2577 		}
2578 		else	/* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2579 		{
2580 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2581 					"select itemid"
2582 					" from items"
2583 					"%s hostid=" ZBX_FS_UI64
2584 						" and",
2585 					operation_item,
2586 					condition_value);
2587 
2588 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
2589 					objectids[i].values, objectids[i].values_num);
2590 		}
2591 
2592 		result = DBselect("%s", sql);
2593 
2594 		while (NULL != (row = DBfetch(result)))
2595 		{
2596 			zbx_uint64_t	objectid;
2597 
2598 			ZBX_STR2UINT64(objectid, row[0]);
2599 			add_condition_match(esc_events, condition, objectid, objects[i]);
2600 		}
2601 		DBfree_result(result);
2602 	}
2603 
2604 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2605 		zbx_vector_uint64_destroy(&objectids[i]);
2606 
2607 	zbx_free(sql);
2608 
2609 	return SUCCEED;
2610 }
2611 
2612 /******************************************************************************
2613  *                                                                            *
2614  * Function: check_intern_application_condition                               *
2615  *                                                                            *
2616  * Purpose: check application condition for internal events                   *
2617  *                                                                            *
2618  * Parameters: esc_events - [IN] events to check                              *
2619  *             condition  - [IN/OUT] condition for matching, outputs          *
2620  *                                   event ids that match condition           *
2621  *                                                                            *
2622  * Return value: SUCCEED - supported operator                                 *
2623  *               NOTSUPPORTED - not supported operator                        *
2624  *                                                                            *
2625  ******************************************************************************/
check_intern_application_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2626 static int	check_intern_application_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2627 {
2628 	char			*sql = NULL;
2629 	size_t			sql_alloc = 0;
2630 	DB_RESULT		result;
2631 	DB_ROW			row;
2632 	int			objects[3] = {EVENT_OBJECT_TRIGGER, EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE}, i, j;
2633 	zbx_vector_uint64_t	objectids[3];
2634 	zbx_uint64_t		objectid;
2635 
2636 	if (CONDITION_OPERATOR_EQUAL != condition->op && CONDITION_OPERATOR_LIKE != condition->op &&
2637 			CONDITION_OPERATOR_NOT_LIKE != condition->op)
2638 		return NOTSUPPORTED;
2639 
2640 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2641 		zbx_vector_uint64_create(&objectids[i]);
2642 
2643 	get_object_ids_internal(esc_events, objectids, objects, (int)ARRSIZE(objects));
2644 
2645 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2646 	{
2647 		size_t	sql_offset = 0;
2648 
2649 		if (0 == objectids[i].values_num)
2650 			continue;
2651 
2652 		if (EVENT_OBJECT_TRIGGER == objects[i])
2653 		{
2654 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2655 					"select distinct t.triggerid,a.name"
2656 					" from applications a,items_applications i,functions f,triggers t"
2657 					" where a.applicationid=i.applicationid"
2658 						" and i.itemid=f.itemid"
2659 						" and f.triggerid=t.triggerid"
2660 						" and");
2661 
2662 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid",
2663 					objectids[i].values, objectids[i].values_num);
2664 		}
2665 		else	/* EVENT_OBJECT_ITEM, EVENT_OBJECT_LLDRULE */
2666 		{
2667 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2668 					"select distinct i.itemid,a.name"
2669 					" from applications a,items_applications i"
2670 					" where a.applicationid=i.applicationid"
2671 						" and");
2672 
2673 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid",
2674 					objectids[i].values, objectids[i].values_num);
2675 		}
2676 
2677 		result = DBselect("%s", sql);
2678 
2679 		switch (condition->op)
2680 		{
2681 			case CONDITION_OPERATOR_EQUAL:
2682 				while (NULL != (row = DBfetch(result)))
2683 				{
2684 					if (0 == strcmp(row[1], condition->value))
2685 					{
2686 						ZBX_STR2UINT64(objectid, row[0]);
2687 						add_condition_match(esc_events, condition, objectid, objects[i]);
2688 					}
2689 				}
2690 				break;
2691 			case CONDITION_OPERATOR_LIKE:
2692 				while (NULL != (row = DBfetch(result)))
2693 				{
2694 					if (NULL != strstr(row[1], condition->value))
2695 					{
2696 						ZBX_STR2UINT64(objectid, row[0]);
2697 						add_condition_match(esc_events, condition, objectid, objects[i]);
2698 					}
2699 				}
2700 				break;
2701 			case CONDITION_OPERATOR_NOT_LIKE:
2702 				while (NULL != (row = DBfetch(result)))
2703 				{
2704 					if (NULL != strstr(row[1], condition->value))
2705 					{
2706 						ZBX_STR2UINT64(objectid, row[0]);
2707 						if (FAIL != (j = zbx_vector_uint64_search(&objectids[i], objectid,
2708 								ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2709 						{
2710 							zbx_vector_uint64_remove_noorder(&objectids[i], j);
2711 						}
2712 					}
2713 				}
2714 
2715 				for (j = 0; j < objectids[i].values_num; j++)
2716 					add_condition_match(esc_events, condition, objectids[i].values[j], objects[i]);
2717 				break;
2718 		}
2719 		DBfree_result(result);
2720 	}
2721 
2722 	for (i = 0; i < (int)ARRSIZE(objects); i++)
2723 		zbx_vector_uint64_destroy(&objectids[i]);
2724 
2725 	zbx_free(sql);
2726 
2727 	return SUCCEED;
2728 }
2729 
2730 /******************************************************************************
2731  *                                                                            *
2732  * Function: check_internal_condition                                         *
2733  *                                                                            *
2734  * Purpose: check if internal event matches single condition                  *
2735  *                                                                            *
2736  * Parameters: event     - [IN] trigger event to check                        *
2737  *             condition - [IN] condition for matching                        *
2738  *                                                                            *
2739  * Return value: SUCCEED - matches, FAIL - otherwise                          *
2740  *                                                                            *
2741  ******************************************************************************/
check_internal_condition(const zbx_vector_ptr_t * esc_events,zbx_condition_t * condition)2742 static void	check_internal_condition(const zbx_vector_ptr_t *esc_events, zbx_condition_t *condition)
2743 {
2744 	int	ret;
2745 
2746 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2747 
2748 	switch (condition->conditiontype)
2749 	{
2750 		case CONDITION_TYPE_EVENT_TYPE:
2751 			ret = check_intern_event_type_condition(esc_events, condition);
2752 			break;
2753 		case CONDITION_TYPE_HOST_GROUP:
2754 			ret = check_intern_host_group_condition(esc_events, condition);
2755 			break;
2756 		case CONDITION_TYPE_HOST_TEMPLATE:
2757 			ret = check_intern_host_template_condition(esc_events, condition);
2758 			break;
2759 		case CONDITION_TYPE_HOST:
2760 			ret = check_intern_host_condition(esc_events, condition);
2761 			break;
2762 		case CONDITION_TYPE_APPLICATION:
2763 			ret = check_intern_application_condition(esc_events, condition);
2764 			break;
2765 		default:
2766 			ret = FAIL;
2767 			zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
2768 					(int)condition->conditiontype, condition->conditionid);
2769 	}
2770 
2771 	if (NOTSUPPORTED == ret)
2772 	{
2773 		zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
2774 				(int)condition->op, condition->conditionid);
2775 	}
2776 
2777 
2778 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2779 }
2780 
2781 /******************************************************************************
2782  *                                                                            *
2783  * Function: check_events_condition                                           *
2784  *                                                                            *
2785  * Purpose: check if multiple events matches single condition                 *
2786  *                                                                            *
2787  * Parameters: esc_events - [IN] events to check                              *
2788  *             source     - [IN] specific event source that need checking     *
2789  *             condition  - [IN/OUT] condition for matching, outputs          *
2790  *                                   event ids that match condition           *
2791  * Author: Alexei Vladishev                                                   *
2792  *                                                                            *
2793  ******************************************************************************/
check_events_condition(const zbx_vector_ptr_t * esc_events,unsigned char source,zbx_condition_t * condition)2794 static void	check_events_condition(const zbx_vector_ptr_t *esc_events, unsigned char source, zbx_condition_t *condition)
2795 {
2796 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'"
2797 			" cond.value2:'%s'", __func__, condition->actionid, condition->conditionid,
2798 			condition->value, condition->value2);
2799 
2800 	switch (source)
2801 	{
2802 		case EVENT_SOURCE_TRIGGERS:
2803 			check_trigger_condition(esc_events, condition);
2804 			break;
2805 		case EVENT_SOURCE_DISCOVERY:
2806 			check_discovery_condition(esc_events, condition);
2807 			break;
2808 		case EVENT_SOURCE_AUTOREGISTRATION:
2809 			check_autoregistration_condition(esc_events, condition);
2810 			break;
2811 		case EVENT_SOURCE_INTERNAL:
2812 			check_internal_condition(esc_events, condition);
2813 			break;
2814 		default:
2815 			zabbix_log(LOG_LEVEL_ERR, "unsupported event source [%d] for condition id [" ZBX_FS_UI64 "]",
2816 					source, condition->conditionid);
2817 	}
2818 
2819 	zbx_vector_uint64_sort(&condition->eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2820 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2821 }
2822 
2823 /******************************************************************************
2824  *                                                                            *
2825  * Function: check_action_condition                                           *
2826  *                                                                            *
2827  * Purpose: check if event matches single condition                           *
2828  *                                                                            *
2829  * Parameters: event - event to check                                         *
2830  *             condition - condition for matching                             *
2831  *                                                                            *
2832  * Return value: SUCCEED - matches, FAIL - otherwise                          *
2833  *                                                                            *
2834  * Author: Alexei Vladishev                                                   *
2835  *                                                                            *
2836  ******************************************************************************/
check_action_condition(const DB_EVENT * event,zbx_condition_t * condition)2837 int	check_action_condition(const DB_EVENT *event, zbx_condition_t *condition)
2838 {
2839 	int			ret;
2840 	zbx_vector_ptr_t	esc_events;
2841 
2842 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'"
2843 			" cond.value2:'%s'", __func__, condition->actionid, condition->conditionid,
2844 			ZBX_NULL2STR(condition->value), ZBX_NULL2STR(condition->value2));
2845 
2846 	zbx_vector_ptr_create(&esc_events);
2847 
2848 	zbx_vector_ptr_append(&esc_events, (DB_EVENT *)event);
2849 
2850 	check_events_condition(&esc_events, event->source, condition);
2851 
2852 	ret = 0 != condition->eventids.values_num ? SUCCEED : FAIL;
2853 
2854 	zbx_vector_ptr_destroy(&esc_events);
2855 
2856 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2857 
2858 	return ret;
2859 }
2860 
2861 /******************************************************************************
2862  *                                                                            *
2863  * Function: check_action_conditions                                          *
2864  *                                                                            *
2865  * Purpose: check if action have to be processed for the event                *
2866  *          (check all conditions of the action)                              *
2867  *                                                                            *
2868  * Parameters: eventid - [IN] the id of event that will be checked            *
2869  *             action  - [IN] action for matching                             *
2870  *                                                                            *
2871  * Return value: SUCCEED - matches, FAIL - otherwise                          *
2872  *                                                                            *
2873  ******************************************************************************/
check_action_conditions(zbx_uint64_t eventid,const zbx_action_eval_t * action)2874 static int	check_action_conditions(zbx_uint64_t eventid, const zbx_action_eval_t *action)
2875 {
2876 	zbx_condition_t	*condition;
2877 	int		condition_result, ret = SUCCEED, id_len, i;
2878 	unsigned char	old_type = 0xff;
2879 	char		*expression = NULL, tmp[ZBX_MAX_UINT64_LEN + 2], *ptr, error[256];
2880 	double		eval_result;
2881 
2882 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " eventsource:%d", __func__,
2883 			action->actionid, (int)action->eventsource);
2884 
2885 	if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
2886 		expression = zbx_strdup(expression, action->formula);
2887 
2888 	for (i = 0; i < action->conditions.values_num; i++)
2889 	{
2890 		condition = (zbx_condition_t *)action->conditions.values[i];
2891 
2892 		if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype && old_type == condition->conditiontype &&
2893 				SUCCEED == ret)
2894 		{
2895 			continue;	/* short-circuit true OR condition block to the next AND condition */
2896 		}
2897 
2898 		condition_result = FAIL == zbx_vector_uint64_bsearch(&condition->eventids, eventid,
2899 				ZBX_DEFAULT_UINT64_COMPARE_FUNC) ? FAIL : SUCCEED;
2900 
2901 		zabbix_log(LOG_LEVEL_DEBUG, " conditionid:" ZBX_FS_UI64 " conditiontype:%d cond.value:'%s' "
2902 				"cond.value2:'%s' result:%s", condition->conditionid, (int)condition->conditiontype,
2903 				condition->value, condition->value2, zbx_result_string(condition_result));
2904 
2905 		switch (action->evaltype)
2906 		{
2907 			case CONDITION_EVAL_TYPE_AND_OR:
2908 				if (old_type == condition->conditiontype)	/* assume conditions are sorted by type */
2909 				{
2910 					if (SUCCEED == condition_result)
2911 						ret = SUCCEED;
2912 				}
2913 				else
2914 				{
2915 					if (FAIL == ret)
2916 						goto clean;
2917 
2918 					ret = condition_result;
2919 					old_type = condition->conditiontype;
2920 				}
2921 
2922 				break;
2923 			case CONDITION_EVAL_TYPE_AND:
2924 				if (FAIL == condition_result)	/* break if any AND condition is FALSE */
2925 				{
2926 					ret = FAIL;
2927 					goto clean;
2928 				}
2929 
2930 				break;
2931 			case CONDITION_EVAL_TYPE_OR:
2932 				if (SUCCEED == condition_result)	/* break if any OR condition is TRUE */
2933 				{
2934 					ret = SUCCEED;
2935 					goto clean;
2936 				}
2937 				ret = FAIL;
2938 
2939 				break;
2940 			case CONDITION_EVAL_TYPE_EXPRESSION:
2941 				zbx_snprintf(tmp, sizeof(tmp), "{" ZBX_FS_UI64 "}", condition->conditionid);
2942 				id_len = strlen(tmp);
2943 
2944 				for (ptr = expression; NULL != (ptr = strstr(ptr, tmp)); ptr += id_len)
2945 				{
2946 					*ptr = (SUCCEED == condition_result ? '1' : '0');
2947 					memset(ptr + 1, ' ', id_len - 1);
2948 				}
2949 
2950 				break;
2951 			default:
2952 				ret = FAIL;
2953 				goto clean;
2954 		}
2955 	}
2956 
2957 	if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
2958 	{
2959 		if (SUCCEED == evaluate(&eval_result, expression, error, sizeof(error), NULL))
2960 			ret = (SUCCEED != zbx_double_compare(eval_result, 0) ? SUCCEED : FAIL);
2961 
2962 		zbx_free(expression);
2963 	}
2964 clean:
2965 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
2966 
2967 	return ret;
2968 }
2969 
2970 /******************************************************************************
2971  *                                                                            *
2972  * Function: execute_operations                                               *
2973  *                                                                            *
2974  * Purpose: execute host, group, template operations linked to the action     *
2975  *                                                                            *
2976  * Parameters: action - action to execute operations for                      *
2977  *                                                                            *
2978  * Author: Alexei Vladishev                                                   *
2979  *                                                                            *
2980  * Comments: for message, command operations see                              *
2981  *           escalation_execute_operations(),                                 *
2982  *           escalation_execute_recovery_operations().                        *
2983  *                                                                            *
2984  ******************************************************************************/
execute_operations(const DB_EVENT * event,zbx_uint64_t actionid)2985 static void	execute_operations(const DB_EVENT *event, zbx_uint64_t actionid)
2986 {
2987 	DB_RESULT		result;
2988 	DB_ROW			row;
2989 	zbx_uint64_t		groupid, templateid;
2990 	zbx_vector_uint64_t	lnk_templateids, del_templateids,
2991 				new_groupids, del_groupids;
2992 	int			i;
2993 
2994 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __func__, actionid);
2995 
2996 	zbx_vector_uint64_create(&lnk_templateids);
2997 	zbx_vector_uint64_create(&del_templateids);
2998 	zbx_vector_uint64_create(&new_groupids);
2999 	zbx_vector_uint64_create(&del_groupids);
3000 
3001 	result = DBselect(
3002 			"select o.operationtype,g.groupid,t.templateid,oi.inventory_mode"
3003 			" from operations o"
3004 				" left join opgroup g on g.operationid=o.operationid"
3005 				" left join optemplate t on t.operationid=o.operationid"
3006 				" left join opinventory oi on oi.operationid=o.operationid"
3007 			" where o.actionid=" ZBX_FS_UI64
3008 			" order by o.operationid",
3009 			actionid);
3010 
3011 	while (NULL != (row = DBfetch(result)))
3012 	{
3013 		int		inventory_mode;
3014 		unsigned char	operationtype;
3015 
3016 		operationtype = (unsigned char)atoi(row[0]);
3017 		ZBX_DBROW2UINT64(groupid, row[1]);
3018 		ZBX_DBROW2UINT64(templateid, row[2]);
3019 		inventory_mode = (SUCCEED == DBis_null(row[3]) ? 0 : atoi(row[3]));
3020 
3021 		switch (operationtype)
3022 		{
3023 			case OPERATION_TYPE_HOST_ADD:
3024 				op_host_add(event);
3025 				break;
3026 			case OPERATION_TYPE_HOST_REMOVE:
3027 				op_host_del(event);
3028 				break;
3029 			case OPERATION_TYPE_HOST_ENABLE:
3030 				op_host_enable(event);
3031 				break;
3032 			case OPERATION_TYPE_HOST_DISABLE:
3033 				op_host_disable(event);
3034 				break;
3035 			case OPERATION_TYPE_GROUP_ADD:
3036 				if (0 != groupid)
3037 					zbx_vector_uint64_append(&new_groupids, groupid);
3038 				break;
3039 			case OPERATION_TYPE_GROUP_REMOVE:
3040 				if (0 != groupid)
3041 					zbx_vector_uint64_append(&del_groupids, groupid);
3042 				break;
3043 			case OPERATION_TYPE_TEMPLATE_ADD:
3044 				if (0 != templateid)
3045 				{
3046 					if (FAIL != (i = zbx_vector_uint64_search(&del_templateids, templateid,
3047 							ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3048 					{
3049 						zbx_vector_uint64_remove(&del_templateids, i);
3050 					}
3051 
3052 					zbx_vector_uint64_append(&lnk_templateids, templateid);
3053 				}
3054 				break;
3055 			case OPERATION_TYPE_TEMPLATE_REMOVE:
3056 				if (0 != templateid)
3057 				{
3058 					if (FAIL != (i = zbx_vector_uint64_search(&lnk_templateids, templateid,
3059 							ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3060 					{
3061 						zbx_vector_uint64_remove(&lnk_templateids, i);
3062 					}
3063 
3064 					zbx_vector_uint64_append(&del_templateids, templateid);
3065 				}
3066 				break;
3067 			case OPERATION_TYPE_HOST_INVENTORY:
3068 				op_host_inventory_mode(event, inventory_mode);
3069 				break;
3070 			default:
3071 				;
3072 		}
3073 	}
3074 	DBfree_result(result);
3075 
3076 	if (0 != del_templateids.values_num)
3077 	{
3078 		zbx_vector_uint64_sort(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3079 		zbx_vector_uint64_uniq(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3080 		op_template_del(event, &del_templateids);
3081 	}
3082 
3083 	if (0 != lnk_templateids.values_num)
3084 	{
3085 		zbx_vector_uint64_sort(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3086 		zbx_vector_uint64_uniq(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3087 		op_template_add(event, &lnk_templateids);
3088 	}
3089 
3090 	if (0 != new_groupids.values_num)
3091 	{
3092 		zbx_vector_uint64_sort(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3093 		zbx_vector_uint64_uniq(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3094 		op_groups_add(event, &new_groupids);
3095 	}
3096 
3097 	if (0 != del_groupids.values_num)
3098 	{
3099 		zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3100 		zbx_vector_uint64_uniq(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3101 		op_groups_del(event, &del_groupids);
3102 	}
3103 
3104 	zbx_vector_uint64_destroy(&del_groupids);
3105 	zbx_vector_uint64_destroy(&new_groupids);
3106 	zbx_vector_uint64_destroy(&del_templateids);
3107 	zbx_vector_uint64_destroy(&lnk_templateids);
3108 
3109 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3110 }
3111 
3112 /* data structures used to create new and recover existing escalations */
3113 
3114 typedef struct
3115 {
3116 	zbx_uint64_t	actionid;
3117 	const DB_EVENT	*event;
3118 }
3119 zbx_escalation_new_t;
3120 
3121 /******************************************************************************
3122  *                                                                            *
3123  * Function: is_recovery_event                                                *
3124  *                                                                            *
3125  * Purpose: checks if the event is recovery event                             *
3126  *                                                                            *
3127  * Parameters: event - [IN] the event to check                                *
3128  *                                                                            *
3129  * Return value: SUCCEED - the event is recovery event                        *
3130  *               FAIL    - otherwise                                          *
3131  *                                                                            *
3132  ******************************************************************************/
is_recovery_event(const DB_EVENT * event)3133 static int	is_recovery_event(const DB_EVENT *event)
3134 {
3135 	if (EVENT_SOURCE_TRIGGERS == event->source)
3136 	{
3137 		if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_VALUE_OK == event->value)
3138 			return SUCCEED;
3139 	}
3140 	else if (EVENT_SOURCE_INTERNAL == event->source)
3141 	{
3142 		switch (event->object)
3143 		{
3144 			case EVENT_OBJECT_TRIGGER:
3145 				if (TRIGGER_STATE_NORMAL == event->value)
3146 					return SUCCEED;
3147 				break;
3148 			case EVENT_OBJECT_ITEM:
3149 				if (ITEM_STATE_NORMAL == event->value)
3150 					return SUCCEED;
3151 				break;
3152 			case EVENT_OBJECT_LLDRULE:
3153 				if (ITEM_STATE_NORMAL == event->value)
3154 					return SUCCEED;
3155 				break;
3156 		}
3157 	}
3158 
3159 	return FAIL;
3160 }
3161 
3162 /******************************************************************************
3163  *                                                                            *
3164  * Function: is_escalation_event                                              *
3165  *                                                                            *
3166  * Purpose: to determine if event needs condition checks                      *
3167  *                                                                            *
3168  * Parameters: event - [IN] event to validate                                 *
3169  *                                                                            *
3170  * Return value: SUCCEED - escalations possible for event                     *
3171  *               FAIL    - escalations not possible for event                 *
3172  *                                                                            *
3173  ******************************************************************************/
is_escalation_event(const DB_EVENT * event)3174 static int	is_escalation_event(const DB_EVENT *event)
3175 {
3176 	/* OK events can't start escalations - skip them */
3177 	if (SUCCEED == is_recovery_event(event))
3178 		return FAIL;
3179 
3180 	if (0 != (event->flags & ZBX_FLAGS_DB_EVENT_NO_ACTION))
3181 		return FAIL;
3182 
3183 	if (0 == (event->flags & ZBX_FLAGS_DB_EVENT_CREATE))
3184 		return FAIL;
3185 
3186 	return SUCCEED;
3187 }
3188 
3189 /******************************************************************************
3190  *                                                                            *
3191  * Function: uniq_conditions_compare_func                                     *
3192  *                                                                            *
3193  * Purpose: compare to find equal conditions                                  *
3194  *                                                                            *
3195  * Parameters: d1 - [IN] condition structure to compare to d2                 *
3196  *             d2 - [IN] condition structure to compare to d1                 *
3197  *                                                                            *
3198  * Return value: 0 - equal                                                    *
3199  *               not 0 - otherwise                                            *
3200  *                                                                            *
3201  ******************************************************************************/
uniq_conditions_compare_func(const void * d1,const void * d2)3202 static int	uniq_conditions_compare_func(const void *d1, const void *d2)
3203 {
3204 	const zbx_condition_t	*condition1 = (const zbx_condition_t *)d1, *condition2 = (const zbx_condition_t *)d2;
3205 	int			ret;
3206 
3207 	ZBX_RETURN_IF_NOT_EQUAL(condition1->conditiontype, condition2->conditiontype);
3208 	ZBX_RETURN_IF_NOT_EQUAL(condition1->op, condition2->op);
3209 
3210 	if (0 != (ret = strcmp(condition1->value, condition2->value)))
3211 		return ret;
3212 
3213 	if (0 != (ret = strcmp(condition1->value2, condition2->value2)))
3214 		return ret;
3215 
3216 	return 0;
3217 }
3218 
3219 /******************************************************************************
3220  *                                                                            *
3221  * Function: uniq_conditions_hash_func                                        *
3222  *                                                                            *
3223  * Purpose: generate hash based on condition values                           *
3224  *                                                                            *
3225  * Parameters: data - [IN] condition structure                                *
3226  *                                                                            *
3227  *                                                                            *
3228  * Return value: hash is generated                                            *
3229  *                                                                            *
3230  ******************************************************************************/
uniq_conditions_hash_func(const void * data)3231 static zbx_hash_t	uniq_conditions_hash_func(const void *data)
3232 {
3233 	const zbx_condition_t	*condition = (const zbx_condition_t *)data;
3234 	zbx_hash_t		hash;
3235 
3236 	hash = ZBX_DEFAULT_STRING_HASH_ALGO(condition->value, strlen(condition->value), ZBX_DEFAULT_HASH_SEED);
3237 	hash = ZBX_DEFAULT_STRING_HASH_ALGO(condition->value2, strlen(condition->value2), hash);
3238 	hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&condition->conditiontype, 1, hash);
3239 	hash = ZBX_DEFAULT_STRING_HASH_ALGO((char *)&condition->op, 1, hash);
3240 
3241 	return hash;
3242 }
3243 
3244 /******************************************************************************
3245  *                                                                            *
3246  * Function: get_escalation_events                                            *
3247  *                                                                            *
3248  * Purpose: add events that have escalation possible and skip others, also    *
3249  *          adds according to source                                          *
3250  *                                                                            *
3251  * Parameters: events       - [IN] events to apply actions for                *
3252  *             events_num   - [IN] number of events                           *
3253  *             esc_events   - [OUT] events that need condition checks         *
3254  *                                                                            *
3255  ******************************************************************************/
get_escalation_events(const zbx_vector_ptr_t * events,zbx_vector_ptr_t * esc_events)3256 static void	get_escalation_events(const zbx_vector_ptr_t *events, zbx_vector_ptr_t *esc_events)
3257 {
3258 	const DB_EVENT	*event;
3259 	int		i;
3260 
3261 	for (i = 0; i < events->values_num; i++)
3262 	{
3263 		event = (DB_EVENT *)events->values[i];
3264 		if (SUCCEED == is_escalation_event(event) && EVENT_SOURCE_COUNT > (size_t)event->source)
3265 			zbx_vector_ptr_append(&esc_events[event->source], (void*)event);
3266 	}
3267 }
3268 
3269 /******************************************************************************
3270  *                                                                            *
3271  * Function: db_condition_clean                                               *
3272  *                                                                            *
3273  * Purpose: cleans condition data structure                                   *
3274  *                                                                            *
3275  * Parameters: condition - [IN] the condition data to free                    *
3276  *                                                                            *
3277  ******************************************************************************/
db_condition_clean(zbx_condition_t * condition)3278 static void	db_condition_clean(zbx_condition_t *condition)
3279 {
3280 	zbx_free(condition->value2);
3281 	zbx_free(condition->value);
3282 	zbx_vector_uint64_destroy(&condition->eventids);
3283 }
3284 
3285 /******************************************************************************
3286  *                                                                            *
3287  * Function: zbx_conditions_eval_clean                                        *
3288  *                                                                            *
3289  * Purpose: cleans condition data structures from hashset                     *
3290  *                                                                            *
3291  * Parameters: uniq_conditions - [IN] hashset with data structures to clean   *
3292  *                                                                            *
3293  ******************************************************************************/
conditions_eval_clean(zbx_hashset_t * uniq_conditions)3294 static void	conditions_eval_clean(zbx_hashset_t *uniq_conditions)
3295 {
3296 	zbx_hashset_iter_t	iter;
3297 	zbx_condition_t		*condition;
3298 
3299 	zbx_hashset_iter_reset(uniq_conditions, &iter);
3300 
3301 	while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3302 		db_condition_clean(condition);
3303 }
3304 
3305 /******************************************************************************
3306  *                                                                            *
3307  * Function: zbx_action_eval_free                                             *
3308  *                                                                            *
3309  * Purpose: frees action evaluation data structure                            *
3310  *                                                                            *
3311  * Parameters: action - [IN] the action evaluation to free                    *
3312  *                                                                            *
3313  ******************************************************************************/
zbx_action_eval_free(zbx_action_eval_t * action)3314 static void	zbx_action_eval_free(zbx_action_eval_t *action)
3315 {
3316 	zbx_free(action->formula);
3317 
3318 	zbx_vector_ptr_destroy(&action->conditions);
3319 
3320 	zbx_free(action);
3321 }
3322 
3323 /******************************************************************************
3324  *                                                                            *
3325  * Function: prepare_actions_conditions_eval                                  *
3326  *                                                                            *
3327  * Purpose: make actions to point, to conditions from hashset, where all      *
3328  *          conditions are unique, this ensures that we don't double check    *
3329  *          same conditions.                                                  *
3330  *                                                                            *
3331  * Parameters: actions         - [IN/OUT] all conditions are added to hashset *
3332  *                                        then cleaned, actions will now      *
3333  *                                        point to conditions from hashset.   *
3334  *                                        for custom expression also          *
3335  *                                        replaces formula                    *
3336  *             uniq_conditions - [OUT]    unique conditions that actions      *
3337  *                                        point to (several sources)          *
3338  *                                                                            *
3339  * Comments: The returned conditions must be freed with                       *
3340  *           conditions_eval_clean() function later.                          *
3341  *                                                                            *
3342  ******************************************************************************/
prepare_actions_conditions_eval(zbx_vector_ptr_t * actions,zbx_hashset_t * uniq_conditions)3343 static void	prepare_actions_conditions_eval(zbx_vector_ptr_t *actions, zbx_hashset_t *uniq_conditions)
3344 {
3345 	int	i, j;
3346 
3347 	for (i = 0; i < actions->values_num; i++)
3348 	{
3349 		zbx_action_eval_t	*action = actions->values[i];
3350 
3351 		for (j = 0; j < action->conditions.values_num; j++)
3352 		{
3353 			zbx_condition_t	*uniq_condition = NULL, *condition = action->conditions.values[j];
3354 
3355 			if (EVENT_SOURCE_COUNT <= action->eventsource)
3356 			{
3357 				db_condition_clean(condition);
3358 			}
3359 			else if (NULL == (uniq_condition = zbx_hashset_search(&uniq_conditions[action->eventsource],
3360 					condition)))
3361 			{
3362 				uniq_condition = zbx_hashset_insert(&uniq_conditions[action->eventsource],
3363 						condition, sizeof(zbx_condition_t));
3364 			}
3365 			else
3366 			{
3367 				if (CONDITION_EVAL_TYPE_EXPRESSION == action->evaltype)
3368 				{
3369 					char	search[ZBX_MAX_UINT64_LEN + 2];
3370 					char	replace[ZBX_MAX_UINT64_LEN + 2];
3371 					char	*old_formula;
3372 
3373 					zbx_snprintf(search, sizeof(search), "{" ZBX_FS_UI64 "}",
3374 							condition->conditionid);
3375 					zbx_snprintf(replace, sizeof(replace), "{" ZBX_FS_UI64 "}",
3376 							uniq_condition->conditionid);
3377 
3378 					old_formula = action->formula;
3379 					action->formula = string_replace(action->formula, search, replace);
3380 					zbx_free(old_formula);
3381 				}
3382 
3383 				db_condition_clean(condition);
3384 			}
3385 
3386 			zbx_free(action->conditions.values[j]);
3387 			action->conditions.values[j] = uniq_condition;
3388 		}
3389 	}
3390 }
3391 
3392 /******************************************************************************
3393  *                                                                            *
3394  * Function: process_actions                                                  *
3395  *                                                                            *
3396  * Purpose: process all actions of each event in a list                       *
3397  *                                                                            *
3398  * Parameters: events        - [IN] events to apply actions for               *
3399  *             closed_events - [IN] a vector of closed event data -           *
3400  *                                  (PROBLEM eventid, OK eventid) pairs.      *
3401  *                                                                            *
3402  ******************************************************************************/
process_actions(const zbx_vector_ptr_t * events,const zbx_vector_uint64_pair_t * closed_events)3403 void	process_actions(const zbx_vector_ptr_t *events, const zbx_vector_uint64_pair_t *closed_events)
3404 {
3405 	int				i;
3406 	zbx_vector_ptr_t		actions;
3407 	zbx_vector_ptr_t 		new_escalations;
3408 	zbx_vector_uint64_pair_t	rec_escalations;
3409 	zbx_hashset_t			uniq_conditions[EVENT_SOURCE_COUNT];
3410 	zbx_vector_ptr_t		esc_events[EVENT_SOURCE_COUNT];
3411 	zbx_hashset_iter_t		iter;
3412 	zbx_condition_t			*condition;
3413 
3414 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() events_num:" ZBX_FS_SIZE_T, __func__, (zbx_fs_size_t)events->values_num);
3415 
3416 	zbx_vector_ptr_create(&new_escalations);
3417 	zbx_vector_uint64_pair_create(&rec_escalations);
3418 
3419 	for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3420 	{
3421 		zbx_hashset_create(&uniq_conditions[i], 0, uniq_conditions_hash_func, uniq_conditions_compare_func);
3422 		zbx_vector_ptr_create(&esc_events[i]);
3423 	}
3424 
3425 	zbx_vector_ptr_create(&actions);
3426 	zbx_dc_get_actions_eval(&actions, ZBX_ACTION_OPCLASS_NORMAL | ZBX_ACTION_OPCLASS_RECOVERY);
3427 	prepare_actions_conditions_eval(&actions, uniq_conditions);
3428 	get_escalation_events(events, esc_events);
3429 
3430 	for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3431 	{
3432 		if (0 == esc_events[i].values_num)
3433 			continue;
3434 
3435 		zbx_vector_ptr_sort(&esc_events[i], compare_events);
3436 
3437 		zbx_hashset_iter_reset(&uniq_conditions[i], &iter);
3438 
3439 		while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3440 			check_events_condition(&esc_events[i], i, condition);
3441 	}
3442 
3443 	/* 1. All event sources: match PROBLEM events to action conditions, add them to 'new_escalations' list.      */
3444 	/* 2. EVENT_SOURCE_DISCOVERY, EVENT_SOURCE_AUTOREGISTRATION: execute operations (except command and message  */
3445 	/*    operations) for events that match action conditions.                                                   */
3446 	for (i = 0; i < events->values_num; i++)
3447 	{
3448 		int		j;
3449 		const DB_EVENT	*event;
3450 
3451 		if (FAIL == is_escalation_event((event = (const DB_EVENT *)events->values[i])))
3452 			continue;
3453 
3454 		for (j = 0; j < actions.values_num; j++)
3455 		{
3456 			zbx_action_eval_t	*action = (zbx_action_eval_t *)actions.values[j];
3457 
3458 			if (action->eventsource != event->source)
3459 				continue;
3460 
3461 			if (SUCCEED == check_action_conditions(event->eventid, action))
3462 			{
3463 				zbx_escalation_new_t	*new_escalation;
3464 
3465 				/* command and message operations handled by escalators even for    */
3466 				/* EVENT_SOURCE_DISCOVERY and EVENT_SOURCE_AUTOREGISTRATION events  */
3467 				new_escalation = (zbx_escalation_new_t *)zbx_malloc(NULL, sizeof(zbx_escalation_new_t));
3468 				new_escalation->actionid = action->actionid;
3469 				new_escalation->event = event;
3470 				zbx_vector_ptr_append(&new_escalations, new_escalation);
3471 
3472 				if (EVENT_SOURCE_DISCOVERY == event->source ||
3473 						EVENT_SOURCE_AUTOREGISTRATION == event->source)
3474 				{
3475 					execute_operations(event, action->actionid);
3476 				}
3477 			}
3478 		}
3479 	}
3480 
3481 	for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3482 	{
3483 		zbx_vector_ptr_destroy(&esc_events[i]);
3484 		conditions_eval_clean(&uniq_conditions[i]);
3485 		zbx_hashset_destroy(&uniq_conditions[i]);
3486 	}
3487 
3488 	zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free);
3489 	zbx_vector_ptr_destroy(&actions);
3490 
3491 	/* 3. Find recovered escalations and store escalationids in 'rec_escalation' by OK eventids. */
3492 	if (0 != closed_events->values_num)
3493 	{
3494 		char			*sql = NULL;
3495 		size_t			sql_alloc = 0, sql_offset = 0;
3496 		zbx_vector_uint64_t	eventids;
3497 		DB_ROW			row;
3498 		DB_RESULT		result;
3499 		int			j, index;
3500 
3501 		zbx_vector_uint64_create(&eventids);
3502 
3503 		/* 3.1. Store PROBLEM eventids of recovered events in 'eventids'. */
3504 		for (j = 0; j < closed_events->values_num; j++)
3505 			zbx_vector_uint64_append(&eventids, closed_events->values[j].first);
3506 
3507 		/* 3.2. Select escalations that must be recovered. */
3508 		zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3509 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3510 				"select eventid,escalationid"
3511 				" from escalations"
3512 				" where");
3513 
3514 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "eventid", eventids.values, eventids.values_num);
3515 		result = DBselect("%s", sql);
3516 
3517 		zbx_vector_uint64_pair_reserve(&rec_escalations, eventids.values_num);
3518 
3519 		/* 3.3. Store the escalationids corresponding to the OK events in 'rec_escalations'. */
3520 		while (NULL != (row = DBfetch(result)))
3521 		{
3522 			zbx_uint64_pair_t	pair;
3523 
3524 			ZBX_STR2UINT64(pair.first, row[0]);
3525 
3526 			if (FAIL == (index = zbx_vector_uint64_pair_bsearch(closed_events, pair,
3527 					ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3528 			{
3529 				THIS_SHOULD_NEVER_HAPPEN;
3530 				continue;
3531 			}
3532 
3533 			pair.second = closed_events->values[index].second;
3534 			ZBX_DBROW2UINT64(pair.first, row[1]);
3535 			zbx_vector_uint64_pair_append(&rec_escalations, pair);
3536 		}
3537 
3538 		DBfree_result(result);
3539 		zbx_free(sql);
3540 		zbx_vector_uint64_destroy(&eventids);
3541 	}
3542 
3543 	/* 4. Create new escalations in DB. */
3544 	if (0 != new_escalations.values_num)
3545 	{
3546 		zbx_db_insert_t	db_insert;
3547 		int		j;
3548 
3549 		zbx_db_insert_prepare(&db_insert, "escalations", "escalationid", "actionid", "status", "triggerid",
3550 					"itemid", "eventid", "r_eventid", "acknowledgeid", NULL);
3551 
3552 		for (j = 0; j < new_escalations.values_num; j++)
3553 		{
3554 			zbx_uint64_t		triggerid = 0, itemid = 0;
3555 			zbx_escalation_new_t	*new_escalation;
3556 
3557 			new_escalation = (zbx_escalation_new_t *)new_escalations.values[j];
3558 
3559 			switch (new_escalation->event->object)
3560 			{
3561 				case EVENT_OBJECT_TRIGGER:
3562 					triggerid = new_escalation->event->objectid;
3563 					break;
3564 				case EVENT_OBJECT_ITEM:
3565 				case EVENT_OBJECT_LLDRULE:
3566 					itemid = new_escalation->event->objectid;
3567 					break;
3568 			}
3569 
3570 			zbx_db_insert_add_values(&db_insert, __UINT64_C(0), new_escalation->actionid,
3571 					(int)ESCALATION_STATUS_ACTIVE, triggerid, itemid,
3572 					new_escalation->event->eventid, __UINT64_C(0), __UINT64_C(0));
3573 
3574 			zbx_free(new_escalation);
3575 		}
3576 
3577 		zbx_db_insert_autoincrement(&db_insert, "escalationid");
3578 		zbx_db_insert_execute(&db_insert);
3579 		zbx_db_insert_clean(&db_insert);
3580 	}
3581 
3582 	/* 5. Modify recovered escalations in DB. */
3583 	if (0 != rec_escalations.values_num)
3584 	{
3585 		char	*sql = NULL;
3586 		size_t	sql_alloc = 0, sql_offset = 0;
3587 		int	j;
3588 
3589 		zbx_vector_uint64_pair_sort(&rec_escalations, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3590 
3591 		DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3592 
3593 		for (j = 0; j < rec_escalations.values_num; j++)
3594 		{
3595 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3596 					"update escalations set r_eventid=" ZBX_FS_UI64 ",nextcheck=0"
3597 					" where escalationid=" ZBX_FS_UI64 ";\n",
3598 					rec_escalations.values[j].second, rec_escalations.values[j].first);
3599 
3600 			DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3601 		}
3602 
3603 		DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3604 
3605 		if (16 < sql_offset)	/* in ORACLE always present begin..end; */
3606 			DBexecute("%s", sql);
3607 
3608 		zbx_free(sql);
3609 	}
3610 
3611 	zbx_vector_uint64_pair_destroy(&rec_escalations);
3612 	zbx_vector_ptr_destroy(&new_escalations);
3613 
3614 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3615 }
3616 
3617 /******************************************************************************
3618  *                                                                            *
3619  * Function: process_actions_by_acknowledgements                              *
3620  *                                                                            *
3621  * Purpose: process actions for each acknowledgement in the array             *
3622  *                                                                            *
3623  * Parameters: event_ack        - [IN] vector for eventid/ackid pairs         *
3624  *                                                                            *
3625  ******************************************************************************/
process_actions_by_acknowledgements(const zbx_vector_ptr_t * ack_tasks)3626 int	process_actions_by_acknowledgements(const zbx_vector_ptr_t *ack_tasks)
3627 {
3628 	zbx_vector_ptr_t	actions;
3629 	zbx_hashset_t		uniq_conditions[EVENT_SOURCE_COUNT];
3630 	int			i, j, k, processed_num = 0, knext = 0;
3631 	zbx_vector_uint64_t	eventids;
3632 	zbx_ack_task_t		*ack_task;
3633 	zbx_vector_ptr_t	ack_escalations, events;
3634 	zbx_ack_escalation_t	*ack_escalation;
3635 	zbx_vector_ptr_t	esc_events[EVENT_SOURCE_COUNT];
3636 	zbx_hashset_iter_t	iter;
3637 	zbx_condition_t		*condition;
3638 
3639 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3640 
3641 	zbx_vector_ptr_create(&ack_escalations);
3642 
3643 	for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3644 	{
3645 		zbx_hashset_create(&uniq_conditions[i], 0, uniq_conditions_hash_func, uniq_conditions_compare_func);
3646 		zbx_vector_ptr_create(&esc_events[i]);
3647 	}
3648 
3649 	zbx_vector_ptr_create(&actions);
3650 	zbx_dc_get_actions_eval(&actions, ZBX_ACTION_OPCLASS_ACKNOWLEDGE);
3651 	prepare_actions_conditions_eval(&actions, uniq_conditions);
3652 
3653 	if (0 == actions.values_num)
3654 		goto out;
3655 
3656 	zbx_vector_uint64_create(&eventids);
3657 
3658 	for (i = 0; i < ack_tasks->values_num; i++)
3659 	{
3660 		ack_task = (zbx_ack_task_t *)ack_tasks->values[i];
3661 		zbx_vector_uint64_append(&eventids, ack_task->eventid);
3662 	}
3663 
3664 	zbx_vector_uint64_sort(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3665 	zbx_vector_uint64_uniq(&eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3666 
3667 	zbx_vector_ptr_create(&events);
3668 
3669 	zbx_db_get_events_by_eventids(&eventids, &events);
3670 
3671 	for (i = 0; i < events.values_num; i++)
3672 	{
3673 		DB_EVENT	*event = (DB_EVENT *)events.values[i];
3674 
3675 		zbx_vector_ptr_append(&esc_events[event->source], (void*)event);
3676 	}
3677 
3678 	for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3679 	{
3680 		if (0 == esc_events[i].values_num)
3681 			continue;
3682 
3683 		zbx_vector_ptr_sort(&esc_events[i], compare_events);
3684 
3685 		zbx_hashset_iter_reset(&uniq_conditions[i], &iter);
3686 
3687 		while (NULL != (condition = (zbx_condition_t *)zbx_hashset_iter_next(&iter)))
3688 			check_events_condition(&esc_events[i], i, condition);
3689 	}
3690 
3691 	for (i = 0; i < eventids.values_num; i++)
3692 	{
3693 		int 		kcurr = knext;
3694 		DB_EVENT	*event = (DB_EVENT *)events.values[i];
3695 
3696 		while (knext < ack_tasks->values_num)
3697 		{
3698 			ack_task = (zbx_ack_task_t *)ack_tasks->values[knext];
3699 			if (ack_task->eventid != event->eventid)
3700 				break;
3701 			knext++;
3702 		}
3703 
3704 		if (0 == event->eventid || 0 == event->trigger.triggerid)
3705 			continue;
3706 
3707 		for (j = 0; j < actions.values_num; j++)
3708 		{
3709 			zbx_action_eval_t	*action = (zbx_action_eval_t *)actions.values[j];
3710 
3711 			if (action->eventsource != event->source)
3712 				continue;
3713 
3714 			if (SUCCEED != check_action_conditions(event->eventid, action))
3715 				continue;
3716 
3717 			for (k = kcurr; k < knext; k++)
3718 			{
3719 				ack_task = (zbx_ack_task_t *)ack_tasks->values[k];
3720 
3721 				ack_escalation = (zbx_ack_escalation_t *)zbx_malloc(NULL, sizeof(zbx_ack_escalation_t));
3722 				ack_escalation->taskid = ack_task->taskid;
3723 				ack_escalation->acknowledgeid = ack_task->acknowledgeid;
3724 				ack_escalation->actionid = action->actionid;
3725 				ack_escalation->eventid = event->eventid;
3726 				ack_escalation->triggerid = event->trigger.triggerid;
3727 				zbx_vector_ptr_append(&ack_escalations, ack_escalation);
3728 			}
3729 		}
3730 	}
3731 
3732 	if (0 != ack_escalations.values_num)
3733 	{
3734 		zbx_db_insert_t	db_insert;
3735 
3736 		zbx_db_insert_prepare(&db_insert, "escalations", "escalationid", "actionid", "status", "triggerid",
3737 						"itemid", "eventid", "r_eventid", "acknowledgeid", NULL);
3738 
3739 		zbx_vector_ptr_sort(&ack_escalations, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3740 
3741 		for (i = 0; i < ack_escalations.values_num; i++)
3742 		{
3743 			ack_escalation = (zbx_ack_escalation_t *)ack_escalations.values[i];
3744 
3745 			zbx_db_insert_add_values(&db_insert, __UINT64_C(0), ack_escalation->actionid,
3746 				(int)ESCALATION_STATUS_ACTIVE, ack_escalation->triggerid, __UINT64_C(0),
3747 				ack_escalation->eventid, __UINT64_C(0), ack_escalation->acknowledgeid);
3748 		}
3749 
3750 		zbx_db_insert_autoincrement(&db_insert, "escalationid");
3751 		zbx_db_insert_execute(&db_insert);
3752 		zbx_db_insert_clean(&db_insert);
3753 
3754 		processed_num = ack_escalations.values_num;
3755 	}
3756 
3757 	zbx_vector_ptr_clear_ext(&events, (zbx_clean_func_t)zbx_db_free_event);
3758 	zbx_vector_ptr_destroy(&events);
3759 
3760 	zbx_vector_uint64_destroy(&eventids);
3761 out:
3762 	for (i = 0; i < EVENT_SOURCE_COUNT; i++)
3763 	{
3764 		zbx_vector_ptr_destroy(&esc_events[i]);
3765 		conditions_eval_clean(&uniq_conditions[i]);
3766 		zbx_hashset_destroy(&uniq_conditions[i]);
3767 	}
3768 
3769 	zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free);
3770 	zbx_vector_ptr_destroy(&actions);
3771 
3772 	zbx_vector_ptr_clear_ext(&ack_escalations, zbx_ptr_free);
3773 	zbx_vector_ptr_destroy(&ack_escalations);
3774 
3775 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() processed_num:%d", __func__, processed_num);
3776 
3777 	return processed_num;
3778 }
3779 
3780 /******************************************************************************
3781  *                                                                            *
3782  * Function: get_actions_info                                                 *
3783  *                                                                            *
3784  * Purpose: reads actions from database                                       *
3785  *                                                                            *
3786  * Parameters: actionids - [IN] requested action ids                          *
3787  *             actions   - [OUT] the array of actions                         *
3788  *                                                                            *
3789  * Comments: use 'free_db_action' function to release allocated memory        *
3790  *                                                                            *
3791  ******************************************************************************/
get_db_actions_info(zbx_vector_uint64_t * actionids,zbx_vector_ptr_t * actions)3792 void	get_db_actions_info(zbx_vector_uint64_t *actionids, zbx_vector_ptr_t *actions)
3793 {
3794 	DB_RESULT	result;
3795 	DB_ROW		row;
3796 	char		*filter = NULL;
3797 	size_t		filter_alloc = 0, filter_offset = 0;
3798 	DB_ACTION	*action;
3799 
3800 	zbx_vector_uint64_sort(actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3801 	zbx_vector_uint64_uniq(actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3802 
3803 	DBadd_condition_alloc(&filter, &filter_alloc, &filter_offset, "actionid", actionids->values,
3804 			actionids->values_num);
3805 
3806 	result = DBselect("select actionid,name,status,eventsource,esc_period,pause_suppressed"
3807 				" from actions"
3808 				" where%s order by actionid", filter);
3809 
3810 	while (NULL != (row = DBfetch(result)))
3811 	{
3812 		char	*tmp;
3813 
3814 		action = (DB_ACTION *)zbx_malloc(NULL, sizeof(DB_ACTION));
3815 		ZBX_STR2UINT64(action->actionid, row[0]);
3816 		ZBX_STR2UCHAR(action->status, row[2]);
3817 		ZBX_STR2UCHAR(action->eventsource, row[3]);
3818 
3819 		tmp = zbx_strdup(NULL, row[4]);
3820 		substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &tmp, MACRO_TYPE_COMMON,
3821 				NULL, 0);
3822 		if (SUCCEED != is_time_suffix(tmp, &action->esc_period, ZBX_LENGTH_UNLIMITED))
3823 		{
3824 			zabbix_log(LOG_LEVEL_WARNING, "Invalid default operation step duration \"%s\" for action"
3825 					" \"%s\", using default value of 1 hour", tmp, row[1]);
3826 			action->esc_period = SEC_PER_HOUR;
3827 		}
3828 		zbx_free(tmp);
3829 
3830 		ZBX_STR2UCHAR(action->pause_suppressed, row[5]);
3831 		action->name = zbx_strdup(NULL, row[1]);
3832 		action->recovery = ZBX_ACTION_RECOVERY_NONE;
3833 
3834 		zbx_vector_ptr_append(actions, action);
3835 	}
3836 	DBfree_result(result);
3837 
3838 	result = DBselect("select actionid from operations where recovery=%d and%s",
3839 			ZBX_OPERATION_MODE_RECOVERY, filter);
3840 
3841 	while (NULL != (row = DBfetch(result)))
3842 	{
3843 		zbx_uint64_t	actionid;
3844 		int		index;
3845 
3846 		ZBX_STR2UINT64(actionid, row[0]);
3847 		if (FAIL != (index = zbx_vector_ptr_bsearch(actions, &actionid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3848 		{
3849 			action = (DB_ACTION *)actions->values[index];
3850 			action->recovery = ZBX_ACTION_RECOVERY_OPERATIONS;
3851 		}
3852 	}
3853 	DBfree_result(result);
3854 
3855 	zbx_free(filter);
3856 }
3857 
free_db_action(DB_ACTION * action)3858 void	free_db_action(DB_ACTION *action)
3859 {
3860 	zbx_free(action->name);
3861 	zbx_free(action);
3862 }
3863