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