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 
28 /******************************************************************************
29  *                                                                            *
30  * Function: check_trigger_condition                                          *
31  *                                                                            *
32  * Purpose: check if event matches single condition                           *
33  *                                                                            *
34  * Parameters: event - trigger event to check                                 *
35  *                                  (event->source == EVENT_SOURCE_TRIGGERS)  *
36  *             condition - condition for matching                             *
37  *                                                                            *
38  * Return value: SUCCEED - matches, FAIL - otherwise                          *
39  *                                                                            *
40  * Author: Alexei Vladishev                                                   *
41  *                                                                            *
42  ******************************************************************************/
check_trigger_condition(const DB_EVENT * event,DB_CONDITION * condition)43 static int	check_trigger_condition(const DB_EVENT *event, DB_CONDITION *condition)
44 {
45 	const char	*__function_name = "check_trigger_condition";
46 	DB_RESULT	result;
47 	DB_ROW		row;
48 	zbx_uint64_t	condition_value;
49 	char		*tmp_str = NULL;
50 	int		ret = FAIL;
51 
52 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
53 
54 	if (CONDITION_TYPE_HOST_GROUP == condition->conditiontype)
55 	{
56 		ZBX_STR2UINT64(condition_value, condition->value);
57 
58 		result = DBselect(
59 				"select distinct hg.groupid"
60 				" from hosts_groups hg,hosts h,items i,functions f,triggers t"
61 				" where hg.hostid=h.hostid"
62 					" and h.hostid=i.hostid"
63 					" and i.itemid=f.itemid"
64 					" and f.triggerid=t.triggerid"
65 					" and t.triggerid=" ZBX_FS_UI64
66 					" and hg.groupid=" ZBX_FS_UI64,
67 				event->objectid,
68 				condition_value);
69 
70 		switch (condition->operator)
71 		{
72 			case CONDITION_OPERATOR_EQUAL:
73 				if (NULL != DBfetch(result))
74 					ret = SUCCEED;
75 				break;
76 			case CONDITION_OPERATOR_NOT_EQUAL:
77 				if (NULL == DBfetch(result))
78 					ret = SUCCEED;
79 				break;
80 			default:
81 				ret = NOTSUPPORTED;
82 		}
83 		DBfree_result(result);
84 	}
85 	else if (CONDITION_TYPE_HOST_TEMPLATE == condition->conditiontype)
86 	{
87 		zbx_uint64_t	hostid, triggerid;
88 
89 		ZBX_STR2UINT64(condition_value, condition->value);
90 
91 		switch (condition->operator)
92 		{
93 			case CONDITION_OPERATOR_EQUAL:
94 			case CONDITION_OPERATOR_NOT_EQUAL:
95 				triggerid = event->objectid;
96 
97 				/* use parent trigger ID for generated triggers */
98 				result = DBselect(
99 						"select parent_triggerid"
100 						" from trigger_discovery"
101 						" where triggerid=" ZBX_FS_UI64,
102 						triggerid);
103 
104 				if (NULL != (row = DBfetch(result)))
105 				{
106 					ZBX_STR2UINT64(triggerid, row[0]);
107 
108 					zabbix_log(LOG_LEVEL_DEBUG, "%s() check host template condition,"
109 							" selecting parent triggerid:" ZBX_FS_UI64,
110 							__function_name, triggerid);
111 				}
112 				DBfree_result(result);
113 
114 				do
115 				{
116 					result = DBselect(
117 							"select distinct i.hostid,t.templateid"
118 							" from items i,functions f,triggers t"
119 							" where i.itemid=f.itemid"
120 								" and f.triggerid=t.templateid"
121 								" and t.triggerid=" ZBX_FS_UI64,
122 							triggerid);
123 
124 					triggerid = 0;
125 
126 					while (NULL != (row = DBfetch(result)))
127 					{
128 						ZBX_STR2UINT64(hostid, row[0]);
129 						ZBX_STR2UINT64(triggerid, row[1]);
130 
131 						if (hostid == condition_value)
132 						{
133 							ret = SUCCEED;
134 							break;
135 						}
136 					}
137 					DBfree_result(result);
138 				}
139 				while (SUCCEED != ret && 0 != triggerid);
140 
141 				if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator)
142 					ret = (SUCCEED == ret) ? FAIL : SUCCEED;
143 				break;
144 			default:
145 				ret = NOTSUPPORTED;
146 		}
147 	}
148 	else if (CONDITION_TYPE_HOST == condition->conditiontype)
149 	{
150 		ZBX_STR2UINT64(condition_value, condition->value);
151 
152 		switch (condition->operator)
153 		{
154 			case CONDITION_OPERATOR_EQUAL:
155 			case CONDITION_OPERATOR_NOT_EQUAL:
156 				result = DBselect(
157 						"select distinct i.hostid"
158 						" from items i,functions f,triggers t"
159 						" where i.itemid=f.itemid"
160 							" and f.triggerid=t.triggerid"
161 							" and t.triggerid=" ZBX_FS_UI64
162 							" and i.hostid=" ZBX_FS_UI64,
163 						event->objectid,
164 						condition_value);
165 
166 				if (NULL != DBfetch(result))
167 					ret = SUCCEED;
168 				DBfree_result(result);
169 
170 				if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator)
171 					ret = (SUCCEED == ret) ? FAIL : SUCCEED;
172 				break;
173 			default:
174 				ret = NOTSUPPORTED;
175 		}
176 	}
177 	else if (CONDITION_TYPE_TRIGGER == condition->conditiontype)
178 	{
179 		zbx_uint64_t	triggerid;
180 
181 		ZBX_STR2UINT64(condition_value, condition->value);
182 
183 		switch (condition->operator)
184 		{
185 			case CONDITION_OPERATOR_EQUAL:
186 			case CONDITION_OPERATOR_NOT_EQUAL:
187 				if (event->objectid == condition_value)
188 				{
189 					ret = SUCCEED;
190 				}
191 				else
192 				{
193 					/* processing of templated triggers */
194 
195 					for (triggerid = event->objectid; 0 != triggerid && FAIL == ret;)
196 					{
197 						result = DBselect(
198 								"select templateid"
199 								" from triggers"
200 								" where triggerid=" ZBX_FS_UI64,
201 								triggerid);
202 
203 						if (NULL == (row = DBfetch(result)))
204 							triggerid = 0;
205 						else
206 						{
207 							ZBX_DBROW2UINT64(triggerid, row[0]);
208 							if (triggerid == condition_value)
209 								ret = SUCCEED;
210 						}
211 						DBfree_result(result);
212 					}
213 				}
214 
215 				if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator)
216 					ret = (SUCCEED == ret) ? FAIL : SUCCEED;
217 				break;
218 			default:
219 				ret = NOTSUPPORTED;
220 		}
221 	}
222 	else if (CONDITION_TYPE_TRIGGER_NAME == condition->conditiontype)
223 	{
224 		tmp_str = zbx_strdup(tmp_str, event->trigger.description);
225 
226 		substitute_simple_macros(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL,
227 				&tmp_str, MACRO_TYPE_TRIGGER_DESCRIPTION, NULL, 0);
228 
229 		switch (condition->operator)
230 		{
231 			case CONDITION_OPERATOR_LIKE:
232 				if (NULL != strstr(tmp_str, condition->value))
233 					ret = SUCCEED;
234 				break;
235 			case CONDITION_OPERATOR_NOT_LIKE:
236 				if (NULL == strstr(tmp_str, condition->value))
237 					ret = SUCCEED;
238 				break;
239 			default:
240 				ret = NOTSUPPORTED;
241 		}
242 		zbx_free(tmp_str);
243 	}
244 	else if (CONDITION_TYPE_TRIGGER_SEVERITY == condition->conditiontype)
245 	{
246 		condition_value = atoi(condition->value);
247 
248 		switch (condition->operator)
249 		{
250 			case CONDITION_OPERATOR_EQUAL:
251 				if (event->trigger.priority == condition_value)
252 					ret = SUCCEED;
253 				break;
254 			case CONDITION_OPERATOR_NOT_EQUAL:
255 				if (event->trigger.priority != condition_value)
256 					ret = SUCCEED;
257 				break;
258 			case CONDITION_OPERATOR_MORE_EQUAL:
259 				if (event->trigger.priority >= condition_value)
260 					ret = SUCCEED;
261 				break;
262 			case CONDITION_OPERATOR_LESS_EQUAL:
263 				if (event->trigger.priority <= condition_value)
264 					ret = SUCCEED;
265 				break;
266 			default:
267 				ret = NOTSUPPORTED;
268 		}
269 	}
270 	else if (CONDITION_TYPE_TRIGGER_VALUE == condition->conditiontype)
271 	{
272 		int	condition_value_i = atoi(condition->value);
273 
274 		switch (condition->operator)
275 		{
276 			case CONDITION_OPERATOR_EQUAL:
277 				if (event->value == condition_value_i)
278 					ret = SUCCEED;
279 				break;
280 			default:
281 				ret = NOTSUPPORTED;
282 		}
283 	}
284 	else if (CONDITION_TYPE_TIME_PERIOD == condition->conditiontype)
285 	{
286 		switch (condition->operator)
287 		{
288 			case CONDITION_OPERATOR_IN:
289 				if (SUCCEED == check_time_period(condition->value, (time_t)event->clock))
290 					ret = SUCCEED;
291 				break;
292 			case CONDITION_OPERATOR_NOT_IN:
293 				if (FAIL == check_time_period(condition->value, (time_t)event->clock))
294 					ret = SUCCEED;
295 				break;
296 			default:
297 				ret = NOTSUPPORTED;
298 		}
299 	}
300 	else if (CONDITION_TYPE_MAINTENANCE == condition->conditiontype)
301 	{
302 		switch (condition->operator)
303 		{
304 			case CONDITION_OPERATOR_IN:
305 				result = DBselect(
306 						"select count(*)"
307 						" from hosts h,items i,functions f,triggers t"
308 						" where h.hostid=i.hostid"
309 							" and h.maintenance_status=%d"
310 							" and i.itemid=f.itemid"
311 							" and f.triggerid=t.triggerid"
312 							" and t.triggerid=" ZBX_FS_UI64,
313 						HOST_MAINTENANCE_STATUS_ON,
314 						event->objectid);
315 
316 				if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0]) && 0 != atoi(row[0]))
317 					ret = SUCCEED;
318 				DBfree_result(result);
319 				break;
320 			case CONDITION_OPERATOR_NOT_IN:
321 				result = DBselect(
322 						"select count(*)"
323 						" from hosts h,items i,functions f,triggers t"
324 						" where h.hostid=i.hostid"
325 							" and h.maintenance_status=%d"
326 							" and i.itemid=f.itemid"
327 							" and f.triggerid=t.triggerid"
328 							" and t.triggerid=" ZBX_FS_UI64,
329 						HOST_MAINTENANCE_STATUS_OFF,
330 						event->objectid);
331 
332 				if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0]) && 0 != atoi(row[0]))
333 					ret = SUCCEED;
334 				DBfree_result(result);
335 				break;
336 			default:
337 				ret = NOTSUPPORTED;
338 		}
339 	}
340 	else if (CONDITION_TYPE_EVENT_ACKNOWLEDGED == condition->conditiontype)
341 	{
342 		result = DBselect(
343 				"select acknowledged"
344 				" from events"
345 				" where acknowledged=%d"
346 					" and eventid=" ZBX_FS_UI64,
347 				atoi(condition->value),
348 				event->eventid);
349 
350 		switch (condition->operator)
351 		{
352 			case CONDITION_OPERATOR_EQUAL:
353 				if (NULL != (row = DBfetch(result)))
354 					ret = SUCCEED;
355 				break;
356 			default:
357 				ret = NOTSUPPORTED;
358 		}
359 		DBfree_result(result);
360 	}
361 	else if (CONDITION_TYPE_APPLICATION == condition->conditiontype)
362 	{
363 		result = DBselect(
364 				"select distinct a.name"
365 				" from applications a,items_applications i,functions f,triggers t"
366 				" where a.applicationid=i.applicationid"
367 					" and i.itemid=f.itemid"
368 					" and f.triggerid=t.triggerid"
369 					" and t.triggerid=" ZBX_FS_UI64,
370 				event->objectid);
371 
372 		switch (condition->operator)
373 		{
374 			case CONDITION_OPERATOR_EQUAL:
375 				while (NULL != (row = DBfetch(result)))
376 				{
377 					if (0 == strcmp(row[0], condition->value))
378 					{
379 						ret = SUCCEED;
380 						break;
381 					}
382 				}
383 				break;
384 			case CONDITION_OPERATOR_LIKE:
385 				while (NULL != (row = DBfetch(result)))
386 				{
387 					if (NULL != strstr(row[0], condition->value))
388 					{
389 						ret = SUCCEED;
390 						break;
391 					}
392 				}
393 				break;
394 			case CONDITION_OPERATOR_NOT_LIKE:
395 				ret = SUCCEED;
396 				while (NULL != (row = DBfetch(result)))
397 				{
398 					if (NULL != strstr(row[0], condition->value))
399 					{
400 						ret = FAIL;
401 						break;
402 					}
403 				}
404 				break;
405 			default:
406 				ret = NOTSUPPORTED;
407 		}
408 		DBfree_result(result);
409 	}
410 	else
411 	{
412 		zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
413 				(int)condition->conditiontype, condition->conditionid);
414 	}
415 
416 	if (NOTSUPPORTED == ret)
417 	{
418 		zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
419 				(int)condition->operator, condition->conditionid);
420 		ret = FAIL;
421 	}
422 
423 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
424 
425 	return ret;
426 }
427 
428 /******************************************************************************
429  *                                                                            *
430  * Function: check_discovery_condition                                        *
431  *                                                                            *
432  * Purpose: check if event matches single condition                           *
433  *                                                                            *
434  * Parameters: event - discovery event to check                               *
435  *                                 (event->source == EVENT_SOURCE_DISCOVERY)  *
436  *             condition - condition for matching                             *
437  *                                                                            *
438  * Return value: SUCCEED - matches, FAIL - otherwise                          *
439  *                                                                            *
440  * Author: Alexei Vladishev                                                   *
441  *                                                                            *
442  ******************************************************************************/
check_discovery_condition(const DB_EVENT * event,DB_CONDITION * condition)443 static int	check_discovery_condition(const DB_EVENT *event, DB_CONDITION *condition)
444 {
445 	const char	*__function_name = "check_discovery_condition";
446 	DB_RESULT	result;
447 	DB_ROW		row;
448 	zbx_uint64_t	condition_value;
449 	int		tmp_int, ret = FAIL;
450 
451 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
452 
453 	if (CONDITION_TYPE_DRULE == condition->conditiontype)
454 	{
455 		ZBX_STR2UINT64(condition_value, condition->value);
456 
457 		if (EVENT_OBJECT_DHOST == event->object)
458 		{
459 			result = DBselect(
460 					"select druleid"
461 					" from dhosts"
462 					" where druleid=" ZBX_FS_UI64
463 						" and dhostid=" ZBX_FS_UI64,
464 					condition_value,
465 					event->objectid);
466 		}
467 		else	/* EVENT_OBJECT_DSERVICE */
468 		{
469 			result = DBselect(
470 					"select h.druleid"
471 					" from dhosts h,dservices s"
472 					" where h.dhostid=s.dhostid"
473 						" and h.druleid=" ZBX_FS_UI64
474 						" and s.dserviceid=" ZBX_FS_UI64,
475 					condition_value,
476 					event->objectid);
477 		}
478 
479 		switch (condition->operator)
480 		{
481 			case CONDITION_OPERATOR_EQUAL:
482 				if (NULL != DBfetch(result))
483 					ret = SUCCEED;
484 				break;
485 			case CONDITION_OPERATOR_NOT_EQUAL:
486 				if (NULL == DBfetch(result))
487 					ret = SUCCEED;
488 				break;
489 			default:
490 				ret = NOTSUPPORTED;
491 		}
492 		DBfree_result(result);
493 	}
494 	else if (CONDITION_TYPE_DCHECK == condition->conditiontype)
495 	{
496 		if (EVENT_OBJECT_DSERVICE == event->object)
497 		{
498 			ZBX_STR2UINT64(condition_value, condition->value);
499 
500 			result = DBselect(
501 					"select dcheckid"
502 					" from dservices"
503 					" where dcheckid=" ZBX_FS_UI64
504 						" and dserviceid=" ZBX_FS_UI64,
505 					condition_value,
506 					event->objectid);
507 
508 			switch (condition->operator)
509 			{
510 				case CONDITION_OPERATOR_EQUAL:
511 					if (NULL != DBfetch(result))
512 						ret = SUCCEED;
513 					break;
514 				case CONDITION_OPERATOR_NOT_EQUAL:
515 					if (NULL == DBfetch(result))
516 						ret = SUCCEED;
517 					break;
518 				default:
519 					ret = NOTSUPPORTED;
520 			}
521 			DBfree_result(result);
522 		}
523 	}
524 	else if (CONDITION_TYPE_DOBJECT == condition->conditiontype)
525 	{
526 		int	condition_value_i = atoi(condition->value);
527 
528 		switch (condition->operator)
529 		{
530 			case CONDITION_OPERATOR_EQUAL:
531 				if (event->object == condition_value_i)
532 					ret = SUCCEED;
533 				break;
534 			default:
535 				ret = NOTSUPPORTED;
536 		}
537 	}
538 	else if (CONDITION_TYPE_PROXY == condition->conditiontype)
539 	{
540 		ZBX_STR2UINT64(condition_value, condition->value);
541 
542 		if (EVENT_OBJECT_DHOST == event->object)
543 		{
544 			result = DBselect(
545 					"select r.proxy_hostid"
546 					" from drules r,dhosts h"
547 					" where r.druleid=h.druleid"
548 						" and r.proxy_hostid=" ZBX_FS_UI64
549 						" and h.dhostid=" ZBX_FS_UI64,
550 					condition_value,
551 					event->objectid);
552 		}
553 		else	/* EVENT_OBJECT_DSERVICE */
554 		{
555 			result = DBselect(
556 					"select r.proxy_hostid"
557 					" from drules r,dhosts h,dservices s"
558 					" where r.druleid=h.druleid"
559 						" and h.dhostid=s.dhostid"
560 						" and r.proxy_hostid=" ZBX_FS_UI64
561 						" and s.dserviceid=" ZBX_FS_UI64,
562 					condition_value,
563 					event->objectid);
564 		}
565 
566 		switch (condition->operator)
567 		{
568 			case CONDITION_OPERATOR_EQUAL:
569 				if (NULL != DBfetch(result))
570 					ret = SUCCEED;
571 				break;
572 			case CONDITION_OPERATOR_NOT_EQUAL:
573 				if (NULL == DBfetch(result))
574 					ret = SUCCEED;
575 				break;
576 			default:
577 				ret = NOTSUPPORTED;
578 		}
579 		DBfree_result(result);
580 	}
581 	else if (CONDITION_TYPE_DVALUE == condition->conditiontype)
582 	{
583 		if (EVENT_OBJECT_DSERVICE == event->object)
584 		{
585 			result = DBselect(
586 					"select value"
587 					" from dservices"
588 					" where dserviceid=" ZBX_FS_UI64,
589 					event->objectid);
590 
591 			if (NULL != (row = DBfetch(result)))
592 			{
593 				switch (condition->operator)
594 				{
595 					case CONDITION_OPERATOR_EQUAL:
596 						if (0 == strcmp(condition->value, row[0]))
597 							ret = SUCCEED;
598 						break;
599 					case CONDITION_OPERATOR_NOT_EQUAL:
600 						if (0 != strcmp(condition->value, row[0]))
601 							ret = SUCCEED;
602 						break;
603 					case CONDITION_OPERATOR_MORE_EQUAL:
604 						if (0 <= strcmp(row[0], condition->value))
605 							ret = SUCCEED;
606 						break;
607 					case CONDITION_OPERATOR_LESS_EQUAL:
608 						if (0 >= strcmp(row[0], condition->value))
609 							ret = SUCCEED;
610 						break;
611 					case CONDITION_OPERATOR_LIKE:
612 						if (NULL != strstr(row[0], condition->value))
613 							ret = SUCCEED;
614 						break;
615 					case CONDITION_OPERATOR_NOT_LIKE:
616 						if (NULL == strstr(row[0], condition->value))
617 							ret = SUCCEED;
618 						break;
619 					default:
620 						ret = NOTSUPPORTED;
621 				}
622 			}
623 			DBfree_result(result);
624 		}
625 	}
626 	else if (CONDITION_TYPE_DHOST_IP == condition->conditiontype)
627 	{
628 		if (EVENT_OBJECT_DHOST == event->object)
629 		{
630 			result = DBselect(
631 					"select distinct ip"
632 					" from dservices"
633 					" where dhostid=" ZBX_FS_UI64,
634 					event->objectid);
635 		}
636 		else
637 		{
638 			result = DBselect(
639 					"select ip"
640 					" from dservices"
641 					" where dserviceid=" ZBX_FS_UI64,
642 					event->objectid);
643 		}
644 
645 		while (NULL != (row = DBfetch(result)) && FAIL == ret)
646 		{
647 			switch (condition->operator)
648 			{
649 				case CONDITION_OPERATOR_EQUAL:
650 					if (SUCCEED == ip_in_list(condition->value, row[0]))
651 						ret = SUCCEED;
652 					break;
653 				case CONDITION_OPERATOR_NOT_EQUAL:
654 					if (SUCCEED != ip_in_list(condition->value, row[0]))
655 						ret = SUCCEED;
656 					break;
657 				default:
658 					ret = NOTSUPPORTED;
659 			}
660 		}
661 		DBfree_result(result);
662 	}
663 	else if (CONDITION_TYPE_DSERVICE_TYPE == condition->conditiontype)
664 	{
665 		if (EVENT_OBJECT_DSERVICE == event->object)
666 		{
667 			int	condition_value_i = atoi(condition->value);
668 
669 			result = DBselect(
670 					"select type"
671 					" from dservices"
672 					" where dserviceid=" ZBX_FS_UI64,
673 					event->objectid);
674 
675 			if (NULL != (row = DBfetch(result)))
676 			{
677 				tmp_int = atoi(row[0]);
678 
679 				switch (condition->operator)
680 				{
681 					case CONDITION_OPERATOR_EQUAL:
682 						if (condition_value_i == tmp_int)
683 							ret = SUCCEED;
684 						break;
685 					case CONDITION_OPERATOR_NOT_EQUAL:
686 						if (condition_value_i != tmp_int)
687 							ret = SUCCEED;
688 						break;
689 					default:
690 						ret = NOTSUPPORTED;
691 				}
692 			}
693 			DBfree_result(result);
694 		}
695 	}
696 	else if (CONDITION_TYPE_DSTATUS == condition->conditiontype)
697 	{
698 		int	condition_value_i = atoi(condition->value);
699 
700 		switch (condition->operator)
701 		{
702 			case CONDITION_OPERATOR_EQUAL:
703 				if (condition_value_i == event->value)
704 					ret = SUCCEED;
705 				break;
706 			case CONDITION_OPERATOR_NOT_EQUAL:
707 				if (condition_value_i != event->value)
708 					ret = SUCCEED;
709 				break;
710 			default:
711 				ret = NOTSUPPORTED;
712 		}
713 	}
714 	else if (CONDITION_TYPE_DUPTIME == condition->conditiontype)
715 	{
716 		int	condition_value_i = atoi(condition->value);
717 
718 		if (EVENT_OBJECT_DHOST == event->object)
719 		{
720 			result = DBselect(
721 					"select status,lastup,lastdown"
722 					" from dhosts"
723 					" where dhostid=" ZBX_FS_UI64,
724 					event->objectid);
725 		}
726 		else
727 		{
728 			result = DBselect(
729 					"select status,lastup,lastdown"
730 					" from dservices"
731 					" where dserviceid=" ZBX_FS_UI64,
732 					event->objectid);
733 		}
734 
735 		if (NULL != (row = DBfetch(result)))
736 		{
737 			int	now;
738 
739 			now = time(NULL);
740 			tmp_int = DOBJECT_STATUS_UP == atoi(row[0]) ? atoi(row[1]) : atoi(row[2]);
741 
742 			switch (condition->operator)
743 			{
744 				case CONDITION_OPERATOR_LESS_EQUAL:
745 					if (0 != tmp_int && (now - tmp_int) <= condition_value_i)
746 						ret = SUCCEED;
747 					break;
748 				case CONDITION_OPERATOR_MORE_EQUAL:
749 					if (0 != tmp_int && (now - tmp_int) >= condition_value_i)
750 						ret = SUCCEED;
751 					break;
752 				default:
753 					ret = NOTSUPPORTED;
754 			}
755 		}
756 		DBfree_result(result);
757 	}
758 	else if (CONDITION_TYPE_DSERVICE_PORT == condition->conditiontype)
759 	{
760 		if (EVENT_OBJECT_DSERVICE == event->object)
761 		{
762 			result = DBselect(
763 					"select port"
764 					" from dservices"
765 					" where dserviceid=" ZBX_FS_UI64,
766 					event->objectid);
767 
768 			if (NULL != (row = DBfetch(result)))
769 			{
770 				switch (condition->operator)
771 				{
772 					case CONDITION_OPERATOR_EQUAL:
773 						if (SUCCEED == int_in_list(condition->value, atoi(row[0])))
774 							ret = SUCCEED;
775 						break;
776 					case CONDITION_OPERATOR_NOT_EQUAL:
777 						if (SUCCEED != int_in_list(condition->value, atoi(row[0])))
778 							ret = SUCCEED;
779 						break;
780 					default:
781 						ret = NOTSUPPORTED;
782 				}
783 			}
784 			DBfree_result(result);
785 		}
786 	}
787 	else
788 	{
789 		zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
790 				(int)condition->conditiontype, condition->conditionid);
791 	}
792 
793 	if (NOTSUPPORTED == ret)
794 	{
795 		zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
796 				(int)condition->operator, condition->conditionid);
797 		ret = FAIL;
798 	}
799 
800 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
801 
802 	return ret;
803 }
804 
805 /******************************************************************************
806  *                                                                            *
807  * Function: check_auto_registration_condition                                *
808  *                                                                            *
809  * Purpose: check if event matches single condition                           *
810  *                                                                            *
811  * Parameters: event - auto registration event to check                       *
812  *                         (event->source == EVENT_SOURCE_AUTO_REGISTRATION)  *
813  *             condition - condition for matching                             *
814  *                                                                            *
815  * Return value: SUCCEED - matches, FAIL - otherwise                          *
816  *                                                                            *
817  * Author: Alexei Vladishev                                                   *
818  *                                                                            *
819  ******************************************************************************/
check_auto_registration_condition(const DB_EVENT * event,DB_CONDITION * condition)820 static int	check_auto_registration_condition(const DB_EVENT *event, DB_CONDITION *condition)
821 {
822 	const char	*__function_name = "check_auto_registration_condition";
823 	DB_RESULT	result;
824 	DB_ROW		row;
825 	zbx_uint64_t	condition_value, id;
826 	int		ret = FAIL;
827 	const char	*condition_field;
828 
829 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
830 
831 	switch (condition->conditiontype)
832 	{
833 		case CONDITION_TYPE_HOST_NAME:
834 		case CONDITION_TYPE_HOST_METADATA:
835 			if (CONDITION_TYPE_HOST_NAME == condition->conditiontype)
836 				condition_field = "host";
837 			else
838 				condition_field = "host_metadata";
839 
840 			result = DBselect(
841 					"select %s"
842 					" from autoreg_host"
843 					" where autoreg_hostid=" ZBX_FS_UI64,
844 					condition_field, event->objectid);
845 
846 			if (NULL != (row = DBfetch(result)))
847 			{
848 				switch (condition->operator)
849 				{
850 					case CONDITION_OPERATOR_LIKE:
851 						if (NULL != strstr(row[0], condition->value))
852 							ret = SUCCEED;
853 						break;
854 					case CONDITION_OPERATOR_NOT_LIKE:
855 						if (NULL == strstr(row[0], condition->value))
856 							ret = SUCCEED;
857 						break;
858 					default:
859 						ret = NOTSUPPORTED;
860 				}
861 			}
862 			DBfree_result(result);
863 
864 			break;
865 		case CONDITION_TYPE_PROXY:
866 			ZBX_STR2UINT64(condition_value, condition->value);
867 
868 			result = DBselect(
869 					"select proxy_hostid"
870 					" from autoreg_host"
871 					" where autoreg_hostid=" ZBX_FS_UI64,
872 					event->objectid);
873 
874 			if (NULL != (row = DBfetch(result)))
875 			{
876 				ZBX_DBROW2UINT64(id, row[0]);
877 
878 				switch (condition->operator)
879 				{
880 					case CONDITION_OPERATOR_EQUAL:
881 						if (id == condition_value)
882 							ret = SUCCEED;
883 						break;
884 					case CONDITION_OPERATOR_NOT_EQUAL:
885 						if (id != condition_value)
886 							ret = SUCCEED;
887 						break;
888 					default:
889 						ret = NOTSUPPORTED;
890 				}
891 			}
892 			DBfree_result(result);
893 
894 			break;
895 		default:
896 			zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
897 					(int)condition->conditiontype, condition->conditionid);
898 	}
899 
900 	if (NOTSUPPORTED == ret)
901 	{
902 		zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
903 				(int)condition->operator, condition->conditionid);
904 		ret = FAIL;
905 	}
906 
907 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
908 
909 	return ret;
910 }
911 
912 /******************************************************************************
913  *                                                                            *
914  * Function: check_internal_condition                                         *
915  *                                                                            *
916  * Purpose: check if internal event matches single condition                  *
917  *                                                                            *
918  * Parameters: event     - [IN] trigger event to check                        *
919  *             condition - [IN] condition for matching                        *
920  *                                                                            *
921  * Return value: SUCCEED - matches, FAIL - otherwise                          *
922  *                                                                            *
923  ******************************************************************************/
check_internal_condition(const DB_EVENT * event,DB_CONDITION * condition)924 static int	check_internal_condition(const DB_EVENT *event, DB_CONDITION *condition)
925 {
926 	const char	*__function_name = "check_internal_condition";
927 	DB_RESULT	result;
928 	DB_ROW		row;
929 	zbx_uint64_t	condition_value;
930 	int		ret = FAIL;
931 	char		sql[256];
932 
933 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
934 
935 	if (EVENT_OBJECT_TRIGGER != event->object && EVENT_OBJECT_ITEM != event->object &&
936 			EVENT_OBJECT_LLDRULE != event->object)
937 	{
938 		zabbix_log(LOG_LEVEL_ERR, "unsupported event object [%d] for condition id [" ZBX_FS_UI64 "]",
939 				event->object, condition->conditionid);
940 		goto out;
941 	}
942 
943 	if (CONDITION_TYPE_EVENT_TYPE == condition->conditiontype)
944 	{
945 		condition_value = atoi(condition->value);
946 
947 		switch (condition_value)
948 		{
949 			case EVENT_TYPE_ITEM_NORMAL:
950 				if (EVENT_OBJECT_ITEM == event->object && ITEM_STATE_NORMAL == event->value)
951 					ret = SUCCEED;
952 				break;
953 			case EVENT_TYPE_ITEM_NOTSUPPORTED:
954 				if (EVENT_OBJECT_ITEM == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
955 					ret = SUCCEED;
956 				break;
957 			case EVENT_TYPE_TRIGGER_NORMAL:
958 				if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_STATE_NORMAL == event->value)
959 					ret = SUCCEED;
960 				break;
961 			case EVENT_TYPE_TRIGGER_UNKNOWN:
962 				if (EVENT_OBJECT_TRIGGER == event->object && TRIGGER_STATE_UNKNOWN == event->value)
963 					ret = SUCCEED;
964 				break;
965 			case EVENT_TYPE_LLDRULE_NORMAL:
966 				if (EVENT_OBJECT_LLDRULE == event->object && ITEM_STATE_NORMAL == event->value)
967 					ret = SUCCEED;
968 				break;
969 			case EVENT_TYPE_LLDRULE_NOTSUPPORTED:
970 				if (EVENT_OBJECT_LLDRULE == event->object && ITEM_STATE_NOTSUPPORTED == event->value)
971 					ret = SUCCEED;
972 				break;
973 			default:
974 				ret = NOTSUPPORTED;
975 		}
976 	}
977 	else if (CONDITION_TYPE_HOST_GROUP == condition->conditiontype)
978 	{
979 		ZBX_STR2UINT64(condition_value, condition->value);
980 
981 		switch (event->object)
982 		{
983 			case EVENT_OBJECT_TRIGGER:
984 				zbx_snprintf(sql, sizeof(sql),
985 						"select null"
986 						" from hosts_groups hg,hosts h,items i,functions f,triggers t"
987 						" where hg.hostid=h.hostid"
988 							" and h.hostid=i.hostid"
989 							" and i.itemid=f.itemid"
990 							" and f.triggerid=t.triggerid"
991 							" and t.triggerid=" ZBX_FS_UI64
992 							" and hg.groupid=" ZBX_FS_UI64,
993 						event->objectid, condition_value);
994 				break;
995 			default:
996 				zbx_snprintf(sql, sizeof(sql),
997 						"select null"
998 						" from hosts_groups hg,hosts h,items i"
999 						" where hg.hostid=h.hostid"
1000 							" and h.hostid=i.hostid"
1001 							" and i.itemid=" ZBX_FS_UI64
1002 							" and hg.groupid=" ZBX_FS_UI64,
1003 						event->objectid, condition_value);
1004 		}
1005 
1006 		result = DBselectN(sql, 1);
1007 
1008 		switch (condition->operator)
1009 		{
1010 			case CONDITION_OPERATOR_EQUAL:
1011 				if (NULL != DBfetch(result))
1012 					ret = SUCCEED;
1013 				break;
1014 			case CONDITION_OPERATOR_NOT_EQUAL:
1015 				if (NULL == DBfetch(result))
1016 					ret = SUCCEED;
1017 				break;
1018 			default:
1019 				ret = NOTSUPPORTED;
1020 		}
1021 		DBfree_result(result);
1022 	}
1023 	else if (CONDITION_TYPE_HOST_TEMPLATE == condition->conditiontype)
1024 	{
1025 		zbx_uint64_t	hostid, objectid;
1026 
1027 		ZBX_STR2UINT64(condition_value, condition->value);
1028 
1029 		switch (condition->operator)
1030 		{
1031 			case CONDITION_OPERATOR_EQUAL:
1032 			case CONDITION_OPERATOR_NOT_EQUAL:
1033 				objectid = event->objectid;
1034 
1035 				/* use parent object ID for generated objects */
1036 				switch (event->object)
1037 				{
1038 					case EVENT_OBJECT_TRIGGER:
1039 						result = DBselect(
1040 								"select parent_triggerid"
1041 								" from trigger_discovery"
1042 								" where triggerid=" ZBX_FS_UI64,
1043 								objectid);
1044 						break;
1045 					default:
1046 						result = DBselect(
1047 								"select id.parent_itemid"
1048 								" from item_discovery id,items i"
1049 								" where id.itemid=i.itemid"
1050 									" and i.itemid=" ZBX_FS_UI64
1051 									" and i.flags=%d",
1052 								objectid, ZBX_FLAG_DISCOVERY_CREATED);
1053 				}
1054 
1055 				if (NULL != (row = DBfetch(result)))
1056 				{
1057 					ZBX_STR2UINT64(objectid, row[0]);
1058 
1059 					zabbix_log(LOG_LEVEL_DEBUG, "%s() check host template condition,"
1060 							" selecting parent objectid:" ZBX_FS_UI64,
1061 							__function_name, objectid);
1062 				}
1063 				DBfree_result(result);
1064 
1065 				do
1066 				{
1067 					switch (event->object)
1068 					{
1069 						case EVENT_OBJECT_TRIGGER:
1070 							result = DBselect(
1071 									"select distinct i.hostid,t.templateid"
1072 									" from items i,functions f,triggers t"
1073 									" where i.itemid=f.itemid"
1074 										" and f.triggerid=t.templateid"
1075 										" and t.triggerid=" ZBX_FS_UI64,
1076 									objectid);
1077 							break;
1078 						default:
1079 							result = DBselect(
1080 									"select t.hostid,t.itemid"
1081 									" from items t,items h"
1082 									" where t.itemid=h.templateid"
1083 										" and h.itemid=" ZBX_FS_UI64,
1084 									objectid);
1085 					}
1086 
1087 					objectid = 0;
1088 
1089 					while (NULL != (row = DBfetch(result)))
1090 					{
1091 						ZBX_STR2UINT64(hostid, row[0]);
1092 						ZBX_STR2UINT64(objectid, row[1]);
1093 
1094 						if (hostid == condition_value)
1095 						{
1096 							ret = SUCCEED;
1097 							break;
1098 						}
1099 					}
1100 					DBfree_result(result);
1101 				}
1102 				while (SUCCEED != ret && 0 != objectid);
1103 
1104 				if (CONDITION_OPERATOR_NOT_EQUAL == condition->operator)
1105 					ret = (SUCCEED == ret) ? FAIL : SUCCEED;
1106 				break;
1107 			default:
1108 				ret = NOTSUPPORTED;
1109 		}
1110 	}
1111 	else if (CONDITION_TYPE_HOST == condition->conditiontype)
1112 	{
1113 		ZBX_STR2UINT64(condition_value, condition->value);
1114 
1115 		switch (event->object)
1116 		{
1117 			case EVENT_OBJECT_TRIGGER:
1118 				zbx_snprintf(sql, sizeof(sql),
1119 						"select null"
1120 						" from items i,functions f,triggers t"
1121 						" where i.itemid=f.itemid"
1122 							" and f.triggerid=t.triggerid"
1123 							" and t.triggerid=" ZBX_FS_UI64
1124 							" and i.hostid=" ZBX_FS_UI64,
1125 						event->objectid, condition_value);
1126 				break;
1127 			default:
1128 				zbx_snprintf(sql, sizeof(sql),
1129 						"select null"
1130 						" from items"
1131 						" where itemid=" ZBX_FS_UI64
1132 							" and hostid=" ZBX_FS_UI64,
1133 						event->objectid, condition_value);
1134 		}
1135 
1136 		result = DBselectN(sql, 1);
1137 
1138 		switch (condition->operator)
1139 		{
1140 			case CONDITION_OPERATOR_EQUAL:
1141 				if (NULL != DBfetch(result))
1142 					ret = SUCCEED;
1143 				break;
1144 			case CONDITION_OPERATOR_NOT_EQUAL:
1145 				if (NULL == DBfetch(result))
1146 					ret = SUCCEED;
1147 				break;
1148 			default:
1149 				ret = NOTSUPPORTED;
1150 		}
1151 		DBfree_result(result);
1152 	}
1153 	else if (CONDITION_TYPE_APPLICATION == condition->conditiontype)
1154 	{
1155 		switch (event->object)
1156 		{
1157 			case EVENT_OBJECT_TRIGGER:
1158 				result = DBselect(
1159 						"select distinct a.name"
1160 						" from applications a,items_applications i,functions f,triggers t"
1161 						" where a.applicationid=i.applicationid"
1162 							" and i.itemid=f.itemid"
1163 							" and f.triggerid=t.triggerid"
1164 							" and t.triggerid=" ZBX_FS_UI64,
1165 						event->objectid);
1166 				break;
1167 			default:
1168 				result = DBselect(
1169 						"select distinct a.name"
1170 						" from applications a,items_applications i"
1171 						" where a.applicationid=i.applicationid"
1172 							" and i.itemid=" ZBX_FS_UI64,
1173 						event->objectid);
1174 		}
1175 
1176 		switch (condition->operator)
1177 		{
1178 			case CONDITION_OPERATOR_EQUAL:
1179 				while (NULL != (row = DBfetch(result)))
1180 				{
1181 					if (0 == strcmp(row[0], condition->value))
1182 					{
1183 						ret = SUCCEED;
1184 						break;
1185 					}
1186 				}
1187 				break;
1188 			case CONDITION_OPERATOR_LIKE:
1189 				while (NULL != (row = DBfetch(result)))
1190 				{
1191 					if (NULL != strstr(row[0], condition->value))
1192 					{
1193 						ret = SUCCEED;
1194 						break;
1195 					}
1196 				}
1197 				break;
1198 			case CONDITION_OPERATOR_NOT_LIKE:
1199 				ret = SUCCEED;
1200 				while (NULL != (row = DBfetch(result)))
1201 				{
1202 					if (NULL != strstr(row[0], condition->value))
1203 					{
1204 						ret = FAIL;
1205 						break;
1206 					}
1207 				}
1208 				break;
1209 			default:
1210 				ret = NOTSUPPORTED;
1211 		}
1212 		DBfree_result(result);
1213 	}
1214 	else
1215 	{
1216 		zabbix_log(LOG_LEVEL_ERR, "unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]",
1217 				(int)condition->conditiontype, condition->conditionid);
1218 	}
1219 
1220 	if (NOTSUPPORTED == ret)
1221 	{
1222 		zabbix_log(LOG_LEVEL_ERR, "unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]",
1223 				(int)condition->operator, condition->conditionid);
1224 		ret = FAIL;
1225 	}
1226 out:
1227 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1228 
1229 	return ret;
1230 }
1231 
1232 /******************************************************************************
1233  *                                                                            *
1234  * Function: check_action_condition                                           *
1235  *                                                                            *
1236  * Purpose: check if event matches single condition                           *
1237  *                                                                            *
1238  * Parameters: event - event to check                                         *
1239  *             condition - condition for matching                             *
1240  *                                                                            *
1241  * Return value: SUCCEED - matches, FAIL - otherwise                          *
1242  *                                                                            *
1243  * Author: Alexei Vladishev                                                   *
1244  *                                                                            *
1245  ******************************************************************************/
check_action_condition(const DB_EVENT * event,DB_CONDITION * condition)1246 int	check_action_condition(const DB_EVENT *event, DB_CONDITION *condition)
1247 {
1248 	const char	*__function_name = "check_action_condition";
1249 	int		ret = FAIL;
1250 
1251 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64 " conditionid:" ZBX_FS_UI64 " cond.value:'%s'",
1252 			__function_name, condition->actionid, condition->conditionid, condition->value);
1253 
1254 	switch (event->source)
1255 	{
1256 		case EVENT_SOURCE_TRIGGERS:
1257 			ret = check_trigger_condition(event, condition);
1258 			break;
1259 		case EVENT_SOURCE_DISCOVERY:
1260 			ret = check_discovery_condition(event, condition);
1261 			break;
1262 		case EVENT_SOURCE_AUTO_REGISTRATION:
1263 			ret = check_auto_registration_condition(event, condition);
1264 			break;
1265 		case EVENT_SOURCE_INTERNAL:
1266 			ret = check_internal_condition(event, condition);
1267 			break;
1268 		default:
1269 			zabbix_log(LOG_LEVEL_ERR, "unsupported event source [%d] for condition id [" ZBX_FS_UI64 "]",
1270 					event->source, condition->conditionid);
1271 	}
1272 
1273 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1274 
1275 	return ret;
1276 }
1277 
1278 /******************************************************************************
1279  *                                                                            *
1280  * Function: check_action_conditions                                          *
1281  *                                                                            *
1282  * Purpose: check if actions have to be processed for the event               *
1283  *          (check all conditions of the action)                              *
1284  *                                                                            *
1285  * Parameters: event - event to check                                         *
1286  *             actionid - action ID for matching                              *
1287  *                                                                            *
1288  * Return value: SUCCEED - matches, FAIL - otherwise                          *
1289  *                                                                            *
1290  * Author: Alexei Vladishev                                                   *
1291  *                                                                            *
1292  ******************************************************************************/
check_action_conditions(const DB_EVENT * event,zbx_action_eval_t * action)1293 static int	check_action_conditions(const DB_EVENT *event, zbx_action_eval_t *action)
1294 {
1295 	const char	*__function_name = "check_action_conditions";
1296 
1297 	DB_CONDITION	*condition;
1298 	int		condition_result, ret = SUCCEED, id_len, i;
1299 	unsigned char	old_type = 0xff;
1300 	char		*expression = NULL, tmp[ZBX_MAX_UINT64_LEN + 2], *ptr, error[256];
1301 	double		eval_result;
1302 
1303 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __function_name, action->actionid);
1304 
1305 	if (action->evaltype == CONDITION_EVAL_TYPE_EXPRESSION)
1306 		expression = zbx_strdup(expression, action->formula);
1307 
1308 	for (i = 0; i < action->conditions.values_num; i++)
1309 	{
1310 		condition = (DB_CONDITION *)action->conditions.values[i];
1311 
1312 		if (CONDITION_EVAL_TYPE_AND_OR == action->evaltype && old_type == condition->conditiontype &&
1313 				SUCCEED == ret)
1314 		{
1315 			continue;	/* short-circuit true OR condition block to the next AND condition */
1316 		}
1317 
1318 		condition_result = check_action_condition(event, condition);
1319 
1320 		switch (action->evaltype)
1321 		{
1322 			case CONDITION_EVAL_TYPE_AND_OR:
1323 				if (old_type == condition->conditiontype)	/* assume conditions are sorted by type */
1324 				{
1325 					if (SUCCEED == condition_result)
1326 						ret = SUCCEED;
1327 				}
1328 				else
1329 				{
1330 					if (FAIL == ret)
1331 						goto clean;
1332 
1333 					ret = condition_result;
1334 					old_type = condition->conditiontype;
1335 				}
1336 
1337 				break;
1338 			case CONDITION_EVAL_TYPE_AND:
1339 				if (FAIL == condition_result)	/* break if any AND condition is FALSE */
1340 				{
1341 					ret = FAIL;
1342 					goto clean;
1343 				}
1344 
1345 				break;
1346 			case CONDITION_EVAL_TYPE_OR:
1347 				if (SUCCEED == condition_result)	/* break if any OR condition is TRUE */
1348 				{
1349 					ret = SUCCEED;
1350 					goto clean;
1351 				}
1352 				ret = FAIL;
1353 
1354 				break;
1355 			case CONDITION_EVAL_TYPE_EXPRESSION:
1356 				zbx_snprintf(tmp, sizeof(tmp), "{" ZBX_FS_UI64 "}", condition->conditionid);
1357 				id_len = strlen(tmp);
1358 
1359 				for (ptr = expression; NULL != (ptr = strstr(ptr, tmp)); ptr += id_len)
1360 				{
1361 					*ptr = (SUCCEED == condition_result ? '1' : '0');
1362 					memset(ptr + 1, ' ', id_len - 1);
1363 				}
1364 
1365 				break;
1366 			default:
1367 				ret = FAIL;
1368 				goto clean;
1369 		}
1370 	}
1371 
1372 	if (action->evaltype == CONDITION_EVAL_TYPE_EXPRESSION)
1373 	{
1374 		if (SUCCEED == evaluate(&eval_result, expression, error, sizeof(error)))
1375 			ret = (SUCCEED != zbx_double_compare(eval_result, 0) ? SUCCEED : FAIL);
1376 
1377 		zbx_free(expression);
1378 	}
1379 clean:
1380 
1381 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1382 
1383 	return ret;
1384 }
1385 
1386 /******************************************************************************
1387  *                                                                            *
1388  * Function: execute_operations                                               *
1389  *                                                                            *
1390  * Purpose: execute all operations linked to the action                       *
1391  *                                                                            *
1392  * Parameters: action - action to execute operations for                      *
1393  *                                                                            *
1394  * Author: Alexei Vladishev                                                   *
1395  *                                                                            *
1396  ******************************************************************************/
execute_operations(const DB_EVENT * event,zbx_uint64_t actionid)1397 static void	execute_operations(const DB_EVENT *event, zbx_uint64_t actionid)
1398 {
1399 	const char		*__function_name = "execute_operations";
1400 
1401 	DB_RESULT		result;
1402 	DB_ROW			row;
1403 	zbx_uint64_t		groupid, templateid;
1404 	zbx_vector_uint64_t	lnk_templateids, del_templateids,
1405 				new_groupids, del_groupids;
1406 
1407 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() actionid:" ZBX_FS_UI64, __function_name, actionid);
1408 
1409 	zbx_vector_uint64_create(&lnk_templateids);
1410 	zbx_vector_uint64_create(&del_templateids);
1411 	zbx_vector_uint64_create(&new_groupids);
1412 	zbx_vector_uint64_create(&del_groupids);
1413 
1414 	result = DBselect(
1415 			"select o.operationtype,g.groupid,t.templateid,oi.inventory_mode"
1416 			" from operations o"
1417 				" left join opgroup g on g.operationid=o.operationid"
1418 				" left join optemplate t on t.operationid=o.operationid"
1419 				" left join opinventory oi on oi.operationid=o.operationid"
1420 			" where o.actionid=" ZBX_FS_UI64,
1421 			actionid);
1422 
1423 	while (NULL != (row = DBfetch(result)))
1424 	{
1425 		int		inventory_mode;
1426 		unsigned char	operationtype;
1427 
1428 		operationtype = (unsigned char)atoi(row[0]);
1429 		ZBX_DBROW2UINT64(groupid, row[1]);
1430 		ZBX_DBROW2UINT64(templateid, row[2]);
1431 		inventory_mode = (SUCCEED == DBis_null(row[3]) ? 0 : atoi(row[3]));
1432 
1433 		switch (operationtype)
1434 		{
1435 			case OPERATION_TYPE_HOST_ADD:
1436 				op_host_add(event);
1437 				break;
1438 			case OPERATION_TYPE_HOST_REMOVE:
1439 				op_host_del(event);
1440 				break;
1441 			case OPERATION_TYPE_HOST_ENABLE:
1442 				op_host_enable(event);
1443 				break;
1444 			case OPERATION_TYPE_HOST_DISABLE:
1445 				op_host_disable(event);
1446 				break;
1447 			case OPERATION_TYPE_GROUP_ADD:
1448 				if (0 != groupid)
1449 					zbx_vector_uint64_append(&new_groupids, groupid);
1450 				break;
1451 			case OPERATION_TYPE_GROUP_REMOVE:
1452 				if (0 != groupid)
1453 					zbx_vector_uint64_append(&del_groupids, groupid);
1454 				break;
1455 			case OPERATION_TYPE_TEMPLATE_ADD:
1456 				if (0 != templateid)
1457 					zbx_vector_uint64_append(&lnk_templateids, templateid);
1458 				break;
1459 			case OPERATION_TYPE_TEMPLATE_REMOVE:
1460 				if (0 != templateid)
1461 					zbx_vector_uint64_append(&del_templateids, templateid);
1462 				break;
1463 			case OPERATION_TYPE_HOST_INVENTORY:
1464 				op_host_inventory_mode(event, inventory_mode);
1465 				break;
1466 			default:
1467 				;
1468 		}
1469 	}
1470 	DBfree_result(result);
1471 
1472 	if (0 != lnk_templateids.values_num)
1473 	{
1474 		zbx_vector_uint64_sort(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1475 		zbx_vector_uint64_uniq(&lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1476 		op_template_add(event, &lnk_templateids);
1477 	}
1478 
1479 	if (0 != del_templateids.values_num)
1480 	{
1481 		zbx_vector_uint64_sort(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1482 		zbx_vector_uint64_uniq(&del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1483 		op_template_del(event, &del_templateids);
1484 	}
1485 
1486 	if (0 != new_groupids.values_num)
1487 	{
1488 		zbx_vector_uint64_sort(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1489 		zbx_vector_uint64_uniq(&new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1490 		op_groups_add(event, &new_groupids);
1491 	}
1492 
1493 	if (0 != del_groupids.values_num)
1494 	{
1495 		zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1496 		zbx_vector_uint64_uniq(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1497 		op_groups_del(event, &del_groupids);
1498 	}
1499 
1500 	zbx_vector_uint64_destroy(&del_groupids);
1501 	zbx_vector_uint64_destroy(&new_groupids);
1502 	zbx_vector_uint64_destroy(&del_templateids);
1503 	zbx_vector_uint64_destroy(&lnk_templateids);
1504 
1505 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1506 }
1507 
escalation_add_values(zbx_db_insert_t * db_insert,int escalations_num,zbx_uint64_t actionid,const DB_EVENT * event,unsigned char recovery)1508 static void	escalation_add_values(zbx_db_insert_t *db_insert, int escalations_num, zbx_uint64_t actionid,
1509 		const DB_EVENT *event, unsigned char recovery)
1510 {
1511 	zbx_uint64_t	escalationid, triggerid = 0, itemid = 0, eventid = 0, r_eventid = 0;
1512 
1513 	if (0 == escalations_num)
1514 	{
1515 		zbx_db_insert_prepare(db_insert, "escalations", "escalationid", "actionid", "status", "triggerid",
1516 				"itemid", "eventid", "r_eventid", NULL);
1517 	}
1518 
1519 	escalationid = DBget_maxid("escalations");
1520 
1521 	switch (event->object)
1522 	{
1523 		case EVENT_OBJECT_TRIGGER:
1524 			triggerid = event->objectid;
1525 			break;
1526 		case EVENT_OBJECT_ITEM:
1527 		case EVENT_OBJECT_LLDRULE:
1528 			itemid = event->objectid;
1529 			break;
1530 	}
1531 
1532 	if (0 == recovery)
1533 		eventid = event->eventid;
1534 	else
1535 		r_eventid = event->eventid;
1536 
1537 	zbx_db_insert_add_values(db_insert, escalationid, actionid, (int)ESCALATION_STATUS_ACTIVE, triggerid, itemid,
1538 			eventid, r_eventid);
1539 }
1540 
1541 /******************************************************************************
1542  *                                                                            *
1543  * Function: process_actions                                                  *
1544  *                                                                            *
1545  * Purpose: process all actions of each event in a list                       *
1546  *                                                                            *
1547  * Parameters: events     - [IN] events to apply actions for                  *
1548  *             events_num - [IN] number of events                             *
1549  *                                                                            *
1550  ******************************************************************************/
process_actions(const DB_EVENT * events,size_t events_num)1551 void	process_actions(const DB_EVENT *events, size_t events_num)
1552 {
1553 	const char			*__function_name = "process_actions";
1554 
1555 	DB_RESULT			result;
1556 	DB_ROW				row;
1557 	zbx_uint64_t			actionid;
1558 	size_t				i;
1559 	zbx_vector_uint64_t		rec_actionids;	/* actionids of possible recovery events */
1560 	zbx_vector_uint64_pair_t	rec_mapping;	/* which action is possibly recovered by which event */
1561 	const DB_EVENT			*event;
1562 	zbx_db_insert_t			db_insert;
1563 	int				escalations_num = 0, j;
1564 	zbx_vector_ptr_t		actions;
1565 
1566 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() events_num:" ZBX_FS_SIZE_T, __function_name, (zbx_fs_size_t)events_num);
1567 
1568 	zbx_vector_uint64_create(&rec_actionids);
1569 	zbx_vector_uint64_pair_create(&rec_mapping);
1570 
1571 	zbx_vector_ptr_create(&actions);
1572 	zbx_dc_get_actions_eval(&actions);
1573 
1574 	for (i = 0; i < events_num; i++)
1575 	{
1576 		event = &events[i];
1577 
1578 		for (j = 0; j < actions.values_num; j++)
1579 		{
1580 			zbx_action_eval_t	*action = (zbx_action_eval_t *)actions.values[j];
1581 
1582 			if (action->eventsource != event->source)
1583 				continue;
1584 
1585 			if (SUCCEED == check_action_conditions(event, action))
1586 			{
1587 				escalation_add_values(&db_insert, escalations_num++, action->actionid, event, 0);
1588 
1589 				if (EVENT_SOURCE_DISCOVERY == event->source ||
1590 						EVENT_SOURCE_AUTO_REGISTRATION == event->source)
1591 				{
1592 					execute_operations(event, action->actionid);
1593 				}
1594 			}
1595 			else if (EVENT_SOURCE_TRIGGERS == event->source || EVENT_SOURCE_INTERNAL == event->source)
1596 			{
1597 				/* Action conditions evaluated to false, but it could be a recovery */
1598 				/* event for this action. Remember this and check escalations later. */
1599 
1600 				zbx_uint64_pair_t	pair;
1601 
1602 				pair.first = action->actionid;
1603 				pair.second = (zbx_uint64_t)i;
1604 
1605 				zbx_vector_uint64_pair_append(&rec_mapping, pair);
1606 
1607 				zbx_vector_uint64_append(&rec_actionids, action->actionid);
1608 			}
1609 		}
1610 	}
1611 
1612 	zbx_vector_ptr_clear_ext(&actions, (zbx_clean_func_t)zbx_action_eval_free);
1613 	zbx_vector_ptr_destroy(&actions);
1614 
1615 	if (0 != rec_actionids.values_num)
1616 	{
1617 		char		*sql = NULL;
1618 		size_t		sql_alloc = 0, sql_offset = 0;
1619 		zbx_uint64_t	triggerid, itemid;
1620 
1621 		zbx_vector_uint64_sort(&rec_actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1622 		zbx_vector_uint64_uniq(&rec_actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1623 
1624 		/* list of ongoing escalations matching actionids collected before */
1625 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1626 				"select actionid,triggerid,itemid"
1627 				" from escalations"
1628 				" where eventid is not null"
1629 					" and");
1630 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "actionid",
1631 				rec_actionids.values, rec_actionids.values_num);
1632 		result = DBselect("%s", sql);
1633 		zbx_free(sql);
1634 
1635 		while (NULL != (row = DBfetch(result)))
1636 		{
1637 			ZBX_STR2UINT64(actionid, row[0]);
1638 			ZBX_DBROW2UINT64(triggerid, row[1]);
1639 			ZBX_DBROW2UINT64(itemid, row[2]);
1640 
1641 			for (j = 0; j < rec_mapping.values_num; j++)
1642 			{
1643 				if (actionid != rec_mapping.values[j].first)
1644 					continue;
1645 
1646 				event = &events[(int)rec_mapping.values[j].second];
1647 
1648 				/* only add recovery if it matches event */
1649 				switch (event->source)
1650 				{
1651 					case EVENT_SOURCE_TRIGGERS:
1652 						if (triggerid != event->objectid)
1653 							continue;
1654 						break;
1655 					case EVENT_SOURCE_INTERNAL:
1656 						switch (event->object)
1657 						{
1658 							case EVENT_OBJECT_TRIGGER:
1659 								if (triggerid != event->objectid)
1660 									continue;
1661 								break;
1662 							case EVENT_OBJECT_ITEM:
1663 							case EVENT_OBJECT_LLDRULE:
1664 								if (itemid != event->objectid)
1665 									continue;
1666 								break;
1667 							default:
1668 								THIS_SHOULD_NEVER_HAPPEN;
1669 						}
1670 
1671 						break;
1672 					default:
1673 						continue;
1674 				}
1675 
1676 				escalation_add_values(&db_insert, escalations_num++, actionid, event, 1);
1677 
1678 				break;
1679 			}
1680 		}
1681 		DBfree_result(result);
1682 	}
1683 
1684 	zbx_vector_uint64_pair_destroy(&rec_mapping);
1685 	zbx_vector_uint64_destroy(&rec_actionids);
1686 
1687 	if (0 != escalations_num)
1688 	{
1689 		zbx_db_insert_execute(&db_insert);
1690 		zbx_db_insert_clean(&db_insert);
1691 	}
1692 
1693 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1694 }
1695