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 "comms.h"
22 #include "db.h"
23 #include "log.h"
24 #include "dbcache.h"
25 
26 #include "operations.h"
27 
28 /******************************************************************************
29  *                                                                            *
30  * Function: select_discovered_host                                           *
31  *                                                                            *
32  * Purpose: select hostid of discovered host                                  *
33  *                                                                            *
34  * Parameters: dhostid - discovered host id                                   *
35  *                                                                            *
36  * Return value: hostid - existing hostid, 0 - if not found                   *
37  *                                                                            *
38  * Author: Alexei Vladishev                                                   *
39  *                                                                            *
40  ******************************************************************************/
select_discovered_host(const DB_EVENT * event)41 static zbx_uint64_t	select_discovered_host(const DB_EVENT *event)
42 {
43 	const char	*__function_name = "select_discovered_host";
44 	DB_RESULT	result;
45 	DB_ROW		row;
46 	zbx_uint64_t	hostid = 0, proxy_hostid;
47 	char		*sql = NULL, *ip_esc;
48 
49 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() eventid:" ZBX_FS_UI64, __function_name, event->eventid);
50 
51 	switch (event->object)
52 	{
53 		case EVENT_OBJECT_DHOST:
54 		case EVENT_OBJECT_DSERVICE:
55 			result = DBselect(
56 					"select dr.proxy_hostid,ds.ip"
57 					" from drules dr,dchecks dc,dservices ds"
58 					" where dc.druleid=dr.druleid"
59 						" and ds.dcheckid=dc.dcheckid"
60 						" and ds.%s=" ZBX_FS_UI64,
61 					EVENT_OBJECT_DSERVICE == event->object ? "dserviceid" : "dhostid",
62 					event->objectid);
63 
64 			if (NULL == (row = DBfetch(result)))
65 			{
66 				DBfree_result(result);
67 				goto exit;
68 			}
69 
70 			ZBX_DBROW2UINT64(proxy_hostid, row[0]);
71 			ip_esc = DBdyn_escape_string(row[1]);
72 			DBfree_result(result);
73 
74 			sql = zbx_dsprintf(sql,
75 					"select h.hostid"
76 					" from hosts h,interface i"
77 					" where h.hostid=i.hostid"
78 						" and i.ip='%s'"
79 						" and i.useip=1"
80 						" and h.status in (%d,%d)"
81 						" and h.proxy_hostid%s"
82 					" order by i.hostid",
83 					ip_esc,
84 					HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
85 					DBsql_id_cmp(proxy_hostid));
86 
87 			zbx_free(ip_esc);
88 			break;
89 		case EVENT_OBJECT_ZABBIX_ACTIVE:
90 			sql = zbx_dsprintf(sql,
91 					"select h.hostid"
92 					" from hosts h,autoreg_host a"
93 					" where h.host=a.host"
94 						" and a.autoreg_hostid=" ZBX_FS_UI64
95 						" and h.status in (%d,%d)",
96 					event->objectid,
97 					HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED);
98 			break;
99 		default:
100 			goto exit;
101 	}
102 
103 	result = DBselectN(sql, 1);
104 
105 	zbx_free(sql);
106 
107 	if (NULL != (row = DBfetch(result)))
108 		ZBX_STR2UINT64(hostid, row[0]);
109 	DBfree_result(result);
110 exit:
111 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():" ZBX_FS_UI64, __function_name, hostid);
112 
113 	return hostid;
114 }
115 
116 /******************************************************************************
117  *                                                                            *
118  * Function: add_discovered_host_groups                                       *
119  *                                                                            *
120  * Purpose: add group to host if not added already                            *
121  *                                                                            *
122  * Author: Alexander Vladishev                                                *
123  *                                                                            *
124  ******************************************************************************/
add_discovered_host_groups(zbx_uint64_t hostid,zbx_vector_uint64_t * groupids)125 static void	add_discovered_host_groups(zbx_uint64_t hostid, zbx_vector_uint64_t *groupids)
126 {
127 	const char	*__function_name = "add_discovered_host_groups";
128 
129 	DB_RESULT	result;
130 	DB_ROW		row;
131 	zbx_uint64_t	groupid;
132 	char		*sql = NULL;
133 	size_t		sql_alloc = 256, sql_offset = 0;
134 	int		i;
135 
136 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
137 
138 	sql = (char *)zbx_malloc(sql, sql_alloc);
139 
140 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
141 			"select groupid"
142 			" from hosts_groups"
143 			" where hostid=" ZBX_FS_UI64
144 				" and",
145 			hostid);
146 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
147 
148 	result = DBselect("%s", sql);
149 
150 	zbx_free(sql);
151 
152 	while (NULL != (row = DBfetch(result)))
153 	{
154 		ZBX_STR2UINT64(groupid, row[0]);
155 
156 		if (FAIL == (i = zbx_vector_uint64_search(groupids, groupid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
157 		{
158 			THIS_SHOULD_NEVER_HAPPEN;
159 			continue;
160 		}
161 
162 		zbx_vector_uint64_remove_noorder(groupids, i);
163 	}
164 	DBfree_result(result);
165 
166 	if (0 != groupids->values_num)
167 	{
168 		zbx_uint64_t	hostgroupid;
169 		zbx_db_insert_t	db_insert;
170 
171 		hostgroupid = DBget_maxid_num("hosts_groups", groupids->values_num);
172 
173 		zbx_db_insert_prepare(&db_insert, "hosts_groups", "hostgroupid", "hostid", "groupid", NULL);
174 
175 		zbx_vector_uint64_sort(groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
176 
177 		for (i = 0; i < groupids->values_num; i++)
178 		{
179 			zbx_db_insert_add_values(&db_insert, hostgroupid++, hostid, groupids->values[i]);
180 		}
181 
182 		zbx_db_insert_execute(&db_insert);
183 		zbx_db_insert_clean(&db_insert);
184 	}
185 
186 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
187 }
188 
189 /******************************************************************************
190  *                                                                            *
191  * Function: add_discovered_host                                              *
192  *                                                                            *
193  * Purpose: add discovered host if it was not added already                   *
194  *                                                                            *
195  * Parameters: dhostid - discovered host id                                   *
196  *                                                                            *
197  * Return value: hostid - new/existing hostid                                 *
198  *                                                                            *
199  * Author: Alexei Vladishev                                                   *
200  *                                                                            *
201  ******************************************************************************/
add_discovered_host(const DB_EVENT * event)202 static zbx_uint64_t	add_discovered_host(const DB_EVENT *event)
203 {
204 	const char		*__function_name = "add_discovered_host";
205 
206 	DB_RESULT		result;
207 	DB_RESULT		result2;
208 	DB_ROW			row;
209 	DB_ROW			row2;
210 	zbx_uint64_t		dhostid, hostid = 0, proxy_hostid;
211 	char			*host = NULL, *host_esc, *host_unique;
212 	unsigned short		port;
213 	zbx_vector_uint64_t	groupids;
214 	unsigned char		svc_type, interface_type;
215 	zbx_config_t		cfg;
216 	zbx_db_insert_t		db_insert;
217 
218 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() eventid:" ZBX_FS_UI64, __function_name, event->eventid);
219 
220 	zbx_vector_uint64_create(&groupids);
221 
222 	zbx_config_get(&cfg, ZBX_CONFIG_FLAGS_DISCOVERY_GROUPID | ZBX_CONFIG_FLAGS_DEFAULT_INVENTORY_MODE);
223 
224 	if (ZBX_DISCOVERY_GROUPID_UNDEFINED == cfg.discovery_groupid)
225 	{
226 		zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host: group for discovered hosts is not defined");
227 		goto clean;
228 	}
229 
230 	zbx_vector_uint64_append(&groupids, cfg.discovery_groupid);
231 
232 	if (EVENT_OBJECT_DHOST == event->object || EVENT_OBJECT_DSERVICE == event->object)
233 	{
234 		if (EVENT_OBJECT_DHOST == event->object)
235 		{
236 			result = DBselect(
237 					"select ds.dhostid,dr.proxy_hostid,ds.ip,ds.dns,ds.port,dc.type"
238 					" from drules dr,dchecks dc,dservices ds"
239 					" where dc.druleid=dr.druleid"
240 						" and ds.dcheckid=dc.dcheckid"
241 						" and ds.dhostid=" ZBX_FS_UI64
242 					" order by ds.dserviceid",
243 					event->objectid);
244 		}
245 		else
246 		{
247 			result = DBselect(
248 					"select ds.dhostid,dr.proxy_hostid,ds.ip,ds.dns,ds.port,dc.type"
249 					" from drules dr,dchecks dc,dservices ds,dservices ds1"
250 					" where dc.druleid=dr.druleid"
251 						" and ds.dcheckid=dc.dcheckid"
252 						" and ds1.dhostid=ds.dhostid"
253 						" and ds1.dserviceid=" ZBX_FS_UI64
254 					" order by ds.dserviceid",
255 					event->objectid);
256 		}
257 
258 		while (NULL != (row = DBfetch(result)))
259 		{
260 			ZBX_STR2UINT64(dhostid, row[0]);
261 			ZBX_DBROW2UINT64(proxy_hostid, row[1]);
262 			svc_type = (unsigned char)atoi(row[5]);
263 
264 			switch (svc_type)
265 			{
266 				case SVC_AGENT:
267 					port = (unsigned short)atoi(row[4]);
268 					interface_type = INTERFACE_TYPE_AGENT;
269 					break;
270 				case SVC_SNMPv1:
271 				case SVC_SNMPv2c:
272 				case SVC_SNMPv3:
273 					port = (unsigned short)atoi(row[4]);
274 					interface_type = INTERFACE_TYPE_SNMP;
275 					break;
276 				default:
277 					port = ZBX_DEFAULT_AGENT_PORT;
278 					interface_type = INTERFACE_TYPE_AGENT;
279 			}
280 
281 			if (0 == hostid)
282 			{
283 				result2 = DBselect(
284 						"select distinct h.hostid"
285 						" from hosts h,interface i,dservices ds"
286 						" where h.hostid=i.hostid"
287 							" and i.ip=ds.ip"
288 							" and h.status in (%d,%d)"
289 							" and h.proxy_hostid%s"
290 							" and ds.dhostid=" ZBX_FS_UI64
291 						" order by h.hostid",
292 						HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
293 						DBsql_id_cmp(proxy_hostid), dhostid);
294 
295 				if (NULL != (row2 = DBfetch(result2)))
296 					ZBX_STR2UINT64(hostid, row2[0]);
297 
298 				DBfree_result(result2);
299 			}
300 
301 			if (0 == hostid)
302 			{
303 				hostid = DBget_maxid("hosts");
304 
305 				/* for host uniqueness purposes */
306 				host = zbx_strdup(host, '\0' != *row[3] ? row[3] : row[2]);
307 
308 				make_hostname(host);	/* replace not-allowed symbols */
309 				host_unique = DBget_unique_hostname_by_sample(host);
310 				zbx_free(host);
311 
312 				zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "proxy_hostid", "host", "name",
313 						NULL);
314 				zbx_db_insert_add_values(&db_insert, hostid, proxy_hostid, host_unique, host_unique);
315 				zbx_db_insert_execute(&db_insert);
316 				zbx_db_insert_clean(&db_insert);
317 
318 				if (HOST_INVENTORY_DISABLED != cfg.default_inventory_mode)
319 					DBadd_host_inventory(hostid, cfg.default_inventory_mode);
320 
321 				DBadd_interface(hostid, interface_type, 1, row[2], row[3], port);
322 
323 				zbx_free(host_unique);
324 
325 				add_discovered_host_groups(hostid, &groupids);
326 			}
327 			else
328 			{
329 				DBadd_interface(hostid, interface_type, 1, row[2], row[3], port);
330 			}
331 		}
332 		DBfree_result(result);
333 	}
334 	else if (EVENT_OBJECT_ZABBIX_ACTIVE == event->object)
335 	{
336 		result = DBselect(
337 				"select proxy_hostid,host,listen_ip,listen_dns,listen_port"
338 				" from autoreg_host"
339 				" where autoreg_hostid=" ZBX_FS_UI64,
340 				event->objectid);
341 
342 		if (NULL != (row = DBfetch(result)))
343 		{
344 			char		*sql = NULL;
345 			zbx_uint64_t	host_proxy_hostid;
346 
347 			ZBX_DBROW2UINT64(proxy_hostid, row[0]);
348 			host_esc = DBdyn_escape_field("hosts", "host", row[1]);
349 			port = (unsigned short)atoi(row[4]);
350 
351 			result2 = DBselect(
352 					"select null"
353 					" from hosts"
354 					" where host='%s'"
355 						" and status=%d",
356 					host_esc, HOST_STATUS_TEMPLATE);
357 
358 			if (NULL != (row2 = DBfetch(result2)))
359 			{
360 				zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host \"%s\":"
361 						" template with the same name already exists", row[1]);
362 				DBfree_result(result2);
363 				goto out;
364 			}
365 			DBfree_result(result2);
366 
367 			sql = zbx_dsprintf(sql,
368 					"select hostid,proxy_hostid"
369 					" from hosts"
370 					" where host='%s'"
371 						" and flags<>%d"
372 						" and status in (%d,%d)"
373 					" order by hostid",
374 					host_esc, ZBX_FLAG_DISCOVERY_PROTOTYPE,
375 					HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED);
376 
377 			result2 = DBselectN(sql, 1);
378 
379 			zbx_free(sql);
380 
381 			if (NULL == (row2 = DBfetch(result2)))
382 			{
383 				hostid = DBget_maxid("hosts");
384 
385 				zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "proxy_hostid", "host", "name",
386 						NULL);
387 				zbx_db_insert_add_values(&db_insert, hostid, proxy_hostid, row[1], row[1]);
388 				zbx_db_insert_execute(&db_insert);
389 				zbx_db_insert_clean(&db_insert);
390 
391 				if (HOST_INVENTORY_DISABLED != cfg.default_inventory_mode)
392 					DBadd_host_inventory(hostid, cfg.default_inventory_mode);
393 
394 				DBadd_interface(hostid, INTERFACE_TYPE_AGENT, 1, row[2], row[3], port);
395 
396 				add_discovered_host_groups(hostid, &groupids);
397 			}
398 			else
399 			{
400 				ZBX_STR2UINT64(hostid, row2[0]);
401 				ZBX_DBROW2UINT64(host_proxy_hostid, row2[1]);
402 
403 				if (host_proxy_hostid != proxy_hostid)
404 				{
405 					DBexecute("update hosts"
406 							" set proxy_hostid=%s"
407 							" where hostid=" ZBX_FS_UI64,
408 							DBsql_id_ins(proxy_hostid), hostid);
409 				}
410 
411 				DBadd_interface(hostid, INTERFACE_TYPE_AGENT, 1, row[2], row[3], port);
412 			}
413 			DBfree_result(result2);
414 out:
415 			zbx_free(host_esc);
416 		}
417 		DBfree_result(result);
418 	}
419 clean:
420 	zbx_config_clean(&cfg);
421 
422 	zbx_vector_uint64_destroy(&groupids);
423 
424 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
425 
426 	return hostid;
427 }
428 
429 /******************************************************************************
430  *                                                                            *
431  * Function: is_discovery_or_auto_registration                                *
432  *                                                                            *
433  * Purpose: checks if the event is discovery or auto registration event       *
434  *                                                                            *
435  * Return value: SUCCEED - it's discovery or auto registration event          *
436  *               FAIL    - otherwise                                          *
437  *                                                                            *
438  ******************************************************************************/
is_discovery_or_auto_registration(const DB_EVENT * event)439 static int	is_discovery_or_auto_registration(const DB_EVENT *event)
440 {
441 	if (event->source == EVENT_SOURCE_DISCOVERY && (event->object == EVENT_OBJECT_DHOST ||
442 			event->object == EVENT_OBJECT_DSERVICE))
443 	{
444 		return SUCCEED;
445 	}
446 
447 	if (event->source == EVENT_SOURCE_AUTOREGISTRATION && event->object == EVENT_OBJECT_ZABBIX_ACTIVE)
448 		return SUCCEED;
449 
450 	return FAIL;
451 }
452 
453 /******************************************************************************
454  *                                                                            *
455  * Function: op_host_add                                                      *
456  *                                                                            *
457  * Purpose: add discovered host                                               *
458  *                                                                            *
459  * Parameters: trigger - trigger data                                         *
460  *             action  - action data                                          *
461  *                                                                            *
462  * Author: Alexei Vladishev                                                   *
463  *                                                                            *
464  ******************************************************************************/
op_host_add(const DB_EVENT * event)465 void	op_host_add(const DB_EVENT *event)
466 {
467 	const char	*__function_name = "op_host_add";
468 
469 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
470 
471 	if (FAIL == is_discovery_or_auto_registration(event))
472 		return;
473 
474 	add_discovered_host(event);
475 
476 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
477 }
478 
479 /******************************************************************************
480  *                                                                            *
481  * Function: op_host_del                                                      *
482  *                                                                            *
483  * Purpose: delete host                                                       *
484  *                                                                            *
485  * Author: Eugene Grigorjev                                                   *
486  *                                                                            *
487  ******************************************************************************/
op_host_del(const DB_EVENT * event)488 void	op_host_del(const DB_EVENT *event)
489 {
490 	const char		*__function_name = "op_host_del";
491 
492 	zbx_vector_uint64_t	hostids;
493 	zbx_uint64_t		hostid;
494 
495 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
496 
497 	if (FAIL == is_discovery_or_auto_registration(event))
498 		return;
499 
500 	if (0 == (hostid = select_discovered_host(event)))
501 		return;
502 
503 	zbx_vector_uint64_create(&hostids);
504 
505 	zbx_vector_uint64_append(&hostids, hostid);
506 
507 	DBdelete_hosts_with_prototypes(&hostids);
508 
509 	zbx_vector_uint64_destroy(&hostids);
510 
511 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
512 }
513 
514 /******************************************************************************
515  *                                                                            *
516  * Function: op_host_enable                                                   *
517  *                                                                            *
518  * Purpose: enable discovered                                                 *
519  *                                                                            *
520  * Author: Alexander Vladishev                                                *
521  *                                                                            *
522  ******************************************************************************/
op_host_enable(const DB_EVENT * event)523 void	op_host_enable(const DB_EVENT *event)
524 {
525 	const char	*__function_name = "op_host_enable";
526 	zbx_uint64_t	hostid;
527 
528 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
529 
530 	if (FAIL == is_discovery_or_auto_registration(event))
531 		return;
532 
533 	if (0 == (hostid = add_discovered_host(event)))
534 		return;
535 
536 	DBexecute(
537 			"update hosts"
538 			" set status=%d"
539 			" where hostid=" ZBX_FS_UI64,
540 			HOST_STATUS_MONITORED,
541 			hostid);
542 
543 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
544 }
545 
546 /******************************************************************************
547  *                                                                            *
548  * Function: op_host_disable                                                  *
549  *                                                                            *
550  * Purpose: disable host                                                      *
551  *                                                                            *
552  * Author: Alexander Vladishev                                                *
553  *                                                                            *
554  ******************************************************************************/
op_host_disable(const DB_EVENT * event)555 void	op_host_disable(const DB_EVENT *event)
556 {
557 	const char	*__function_name = "op_host_disable";
558 	zbx_uint64_t	hostid;
559 
560 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
561 
562 	if (FAIL == is_discovery_or_auto_registration(event))
563 		return;
564 
565 	if (0 == (hostid = add_discovered_host(event)))
566 		return;
567 
568 	DBexecute(
569 			"update hosts"
570 			" set status=%d"
571 			" where hostid=" ZBX_FS_UI64,
572 			HOST_STATUS_NOT_MONITORED,
573 			hostid);
574 
575 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
576 }
577 
578 /******************************************************************************
579  *                                                                            *
580  * Function: op_host_inventory_mode                                           *
581  *                                                                            *
582  * Purpose: sets host inventory mode                                          *
583  *                                                                            *
584  * Parameters: event          - [IN] the source event                         *
585  *             inventory_mode - [IN] the new inventory mode, see              *
586  *                              HOST_INVENTORY_ defines                       *
587  *                                                                            *
588  * Comments: This function does not allow disabling host inventory - only     *
589  *           setting manual or automatic host inventory mode is supported.    *
590  *                                                                            *
591  ******************************************************************************/
op_host_inventory_mode(const DB_EVENT * event,int inventory_mode)592 void	op_host_inventory_mode(const DB_EVENT *event, int inventory_mode)
593 {
594 	const char	*__function_name = "op_host_inventory_mode";
595 	zbx_uint64_t	hostid;
596 
597 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
598 
599 	if (FAIL == is_discovery_or_auto_registration(event))
600 		return;
601 
602 	if (0 == (hostid = add_discovered_host(event)))
603 		return;
604 
605 	DBset_host_inventory(hostid, inventory_mode);
606 
607 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
608 }
609 
610 /******************************************************************************
611  *                                                                            *
612  * Function: op_groups_add                                                    *
613  *                                                                            *
614  * Purpose: add groups to discovered host                                     *
615  *                                                                            *
616  * Parameters: event    - [IN] event data                                     *
617  *             groupids - [IN] IDs of groups to add                           *
618  *                                                                            *
619  * Author: Alexei Vladishev                                                   *
620  *                                                                            *
621  ******************************************************************************/
op_groups_add(const DB_EVENT * event,zbx_vector_uint64_t * groupids)622 void	op_groups_add(const DB_EVENT *event, zbx_vector_uint64_t *groupids)
623 {
624 	const char	*__function_name = "op_groups_add";
625 	zbx_uint64_t	hostid;
626 
627 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
628 
629 	if (FAIL == is_discovery_or_auto_registration(event))
630 		return;
631 
632 	if (0 == (hostid = add_discovered_host(event)))
633 		return;
634 
635 	add_discovered_host_groups(hostid, groupids);
636 
637 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
638 }
639 
640 /******************************************************************************
641  *                                                                            *
642  * Function: op_groups_del                                                    *
643  *                                                                            *
644  * Purpose: delete groups from discovered host                                *
645  *                                                                            *
646  * Parameters: event    - [IN] event data                                     *
647  *             groupids - [IN] IDs of groups to delete                        *
648  *                                                                            *
649  * Author: Alexei Vladishev                                                   *
650  *                                                                            *
651  ******************************************************************************/
op_groups_del(const DB_EVENT * event,zbx_vector_uint64_t * groupids)652 void	op_groups_del(const DB_EVENT *event, zbx_vector_uint64_t *groupids)
653 {
654 	const char	*__function_name = "op_groups_del";
655 
656 	DB_RESULT	result;
657 	zbx_uint64_t	hostid;
658 	char		*sql = NULL;
659 	size_t		sql_alloc = 256, sql_offset = 0;
660 
661 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
662 
663 	if (FAIL == is_discovery_or_auto_registration(event))
664 		return;
665 
666 	if (0 == (hostid = select_discovered_host(event)))
667 		return;
668 
669 	sql = (char *)zbx_malloc(sql, sql_alloc);
670 
671 	/* make sure host belongs to at least one hostgroup */
672 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
673 			"select groupid"
674 			" from hosts_groups"
675 			" where hostid=" ZBX_FS_UI64
676 				" and not",
677 			hostid);
678 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
679 
680 	result = DBselectN(sql, 1);
681 
682 	if (NULL == DBfetch(result))
683 	{
684 		zabbix_log(LOG_LEVEL_WARNING, "cannot remove host \"%s\" from all host groups:"
685 				" it must belong to at least one", zbx_host_string(hostid));
686 	}
687 	else
688 	{
689 		sql_offset = 0;
690 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
691 				"delete from hosts_groups"
692 				" where hostid=" ZBX_FS_UI64
693 					" and",
694 				hostid);
695 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
696 
697 		DBexecute("%s", sql);
698 	}
699 	DBfree_result(result);
700 
701 	zbx_free(sql);
702 
703 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
704 }
705 
706 /******************************************************************************
707  *                                                                            *
708  * Function: op_template_add                                                  *
709  *                                                                            *
710  * Purpose: link host with template                                           *
711  *                                                                            *
712  * Parameters: event           - [IN] event data                              *
713  *             lnk_templateids - [IN] array of template IDs                   *
714  *                                                                            *
715  * Author: Eugene Grigorjev                                                   *
716  *                                                                            *
717  ******************************************************************************/
op_template_add(const DB_EVENT * event,zbx_vector_uint64_t * lnk_templateids)718 void	op_template_add(const DB_EVENT *event, zbx_vector_uint64_t *lnk_templateids)
719 {
720 	const char	*__function_name = "op_template_add";
721 	zbx_uint64_t	hostid;
722 	char		*error;
723 
724 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
725 
726 	if (FAIL == is_discovery_or_auto_registration(event))
727 		return;
728 
729 	if (0 == (hostid = add_discovered_host(event)))
730 		return;
731 
732 	if (SUCCEED != DBcopy_template_elements(hostid, lnk_templateids, &error))
733 	{
734 		zabbix_log(LOG_LEVEL_WARNING, "cannot link template(s) %s", error);
735 		zbx_free(error);
736 	}
737 
738 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
739 }
740 
741 /******************************************************************************
742  *                                                                            *
743  * Function: op_template_del                                                  *
744  *                                                                            *
745  * Purpose: unlink and clear host from template                               *
746  *                                                                            *
747  * Parameters: event           - [IN] event data                              *
748  *             lnk_templateids - [IN] array of template IDs                   *
749  *                                                                            *
750  * Author: Eugene Grigorjev                                                   *
751  *                                                                            *
752  ******************************************************************************/
op_template_del(const DB_EVENT * event,zbx_vector_uint64_t * del_templateids)753 void	op_template_del(const DB_EVENT *event, zbx_vector_uint64_t *del_templateids)
754 {
755 	const char	*__function_name = "op_template_del";
756 	zbx_uint64_t	hostid;
757 	char		*error;
758 
759 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
760 
761 	if (FAIL == is_discovery_or_auto_registration(event))
762 		return;
763 
764 	if (0 == (hostid = select_discovered_host(event)))
765 		return;
766 
767 	if (SUCCEED != DBdelete_template_elements(hostid, del_templateids, &error))
768 	{
769 		zabbix_log(LOG_LEVEL_WARNING, "cannot unlink template: %s", error);
770 		zbx_free(error);
771 	}
772 
773 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
774 }
775