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 "lld.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxalgo.h"
24 #include "zbxserver.h"
25 
26 typedef struct
27 {
28 	zbx_uint64_t	hostmacroid;
29 	char		*macro;
30 	char		*value;
31 }
32 zbx_lld_hostmacro_t;
33 
lld_hostmacro_free(zbx_lld_hostmacro_t * hostmacro)34 static void	lld_hostmacro_free(zbx_lld_hostmacro_t *hostmacro)
35 {
36 	zbx_free(hostmacro->macro);
37 	zbx_free(hostmacro->value);
38 	zbx_free(hostmacro);
39 }
40 
41 typedef struct
42 {
43 	zbx_uint64_t	interfaceid;
44 	zbx_uint64_t	parent_interfaceid;
45 	char		*ip;
46 	char		*dns;
47 	char		*port;
48 	unsigned char	main;
49 	unsigned char	main_orig;
50 	unsigned char	type;
51 	unsigned char	type_orig;
52 	unsigned char	useip;
53 	unsigned char	bulk;
54 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE	__UINT64_C(0x00000001)	/* interface.type field should be updated  */
55 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN	__UINT64_C(0x00000002)	/* interface.main field should be updated */
56 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP	__UINT64_C(0x00000004)	/* interface.useip field should be updated */
57 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_IP	__UINT64_C(0x00000008)	/* interface.ip field should be updated */
58 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS	__UINT64_C(0x00000010)	/* interface.dns field should be updated */
59 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT	__UINT64_C(0x00000020)	/* interface.port field should be updated */
60 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_BULK	__UINT64_C(0x00000040)	/* interface.bulk field should be updated */
61 #define ZBX_FLAG_LLD_INTERFACE_UPDATE								\
62 		(ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE | ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN |	\
63 		ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP | ZBX_FLAG_LLD_INTERFACE_UPDATE_IP |	\
64 		ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS | ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT |	\
65 		ZBX_FLAG_LLD_INTERFACE_UPDATE_BULK)
66 #define ZBX_FLAG_LLD_INTERFACE_REMOVE		__UINT64_C(0x00000080)	/* interfaces which should be deleted */
67 	zbx_uint64_t	flags;
68 }
69 zbx_lld_interface_t;
70 
lld_interface_free(zbx_lld_interface_t * interface)71 static void	lld_interface_free(zbx_lld_interface_t *interface)
72 {
73 	zbx_free(interface->port);
74 	zbx_free(interface->dns);
75 	zbx_free(interface->ip);
76 	zbx_free(interface);
77 }
78 
79 typedef struct
80 {
81 	zbx_uint64_t		hostid;
82 	zbx_vector_uint64_t	new_groupids;		/* host groups which should be added */
83 	zbx_vector_uint64_t	lnk_templateids;	/* templates which should be linked */
84 	zbx_vector_uint64_t	del_templateids;	/* templates which should be unlinked */
85 	zbx_vector_ptr_t	new_hostmacros;		/* host macros which should be added */
86 	zbx_vector_ptr_t	interfaces;
87 	char			*host_proto;
88 	char			*host;
89 	char			*host_orig;
90 	char			*name;
91 	char			*name_orig;
92 	int			lastcheck;
93 	int			ts_delete;
94 
95 #define ZBX_FLAG_LLD_HOST_DISCOVERED			__UINT64_C(0x00000001)	/* hosts which should be updated or added */
96 #define ZBX_FLAG_LLD_HOST_UPDATE_HOST			__UINT64_C(0x00000002)	/* hosts.host and host_discovery.host fields should be updated */
97 #define ZBX_FLAG_LLD_HOST_UPDATE_NAME			__UINT64_C(0x00000004)	/* hosts.name field should be updated */
98 #define ZBX_FLAG_LLD_HOST_UPDATE_PROXY			__UINT64_C(0x00000008)	/* hosts.proxy_hostid field should be updated */
99 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH		__UINT64_C(0x00000010)	/* hosts.ipmi_authtype field should be updated */
100 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV		__UINT64_C(0x00000020)	/* hosts.ipmi_privilege field should be updated */
101 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER		__UINT64_C(0x00000040)	/* hosts.ipmi_username field should be updated */
102 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS		__UINT64_C(0x00000080)	/* hosts.ipmi_password field should be updated */
103 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT		__UINT64_C(0x00000100)	/* hosts.tls_connect field should be updated */
104 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT		__UINT64_C(0x00000200)	/* hosts.tls_accept field should be updated */
105 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER		__UINT64_C(0x00000400)	/* hosts.tls_issuer field should be updated */
106 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT		__UINT64_C(0x00000800)	/* hosts.tls_subject field should be updated */
107 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY	__UINT64_C(0x00001000)	/* hosts.tls_psk_identity field should be updated */
108 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK		__UINT64_C(0x00002000)	/* hosts.tls_psk field should be updated */
109 
110 #define ZBX_FLAG_LLD_HOST_UPDATE									\
111 		(ZBX_FLAG_LLD_HOST_UPDATE_HOST | ZBX_FLAG_LLD_HOST_UPDATE_NAME |			\
112 		ZBX_FLAG_LLD_HOST_UPDATE_PROXY | ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH |			\
113 		ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV | ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER |		\
114 		ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS | ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT |		\
115 		ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT | ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER |		\
116 		ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT | ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY |	\
117 		ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK)
118 
119 	zbx_uint64_t		flags;
120 	char			inventory_mode;
121 }
122 zbx_lld_host_t;
123 
lld_host_free(zbx_lld_host_t * host)124 static void	lld_host_free(zbx_lld_host_t *host)
125 {
126 	zbx_vector_uint64_destroy(&host->new_groupids);
127 	zbx_vector_uint64_destroy(&host->lnk_templateids);
128 	zbx_vector_uint64_destroy(&host->del_templateids);
129 	zbx_vector_ptr_clear_ext(&host->new_hostmacros, (zbx_clean_func_t)lld_hostmacro_free);
130 	zbx_vector_ptr_destroy(&host->new_hostmacros);
131 	zbx_vector_ptr_clear_ext(&host->interfaces, (zbx_clean_func_t)lld_interface_free);
132 	zbx_vector_ptr_destroy(&host->interfaces);
133 	zbx_free(host->host_proto);
134 	zbx_free(host->host);
135 	zbx_free(host->host_orig);
136 	zbx_free(host->name);
137 	zbx_free(host->name_orig);
138 	zbx_free(host);
139 }
140 
141 typedef struct
142 {
143 	zbx_uint64_t	group_prototypeid;
144 	char		*name;
145 }
146 zbx_lld_group_prototype_t;
147 
lld_group_prototype_free(zbx_lld_group_prototype_t * group_prototype)148 static void	lld_group_prototype_free(zbx_lld_group_prototype_t *group_prototype)
149 {
150 	zbx_free(group_prototype->name);
151 	zbx_free(group_prototype);
152 }
153 
154 typedef struct
155 {
156 	zbx_uint64_t		groupid;
157 	zbx_uint64_t		group_prototypeid;
158 	zbx_vector_ptr_t	hosts;
159 	char			*name_proto;
160 	char			*name;
161 	char			*name_orig;
162 	int			lastcheck;
163 	int			ts_delete;
164 #define ZBX_FLAG_LLD_GROUP_DISCOVERED		__UINT64_C(0x00000001)	/* groups which should be updated or added */
165 #define ZBX_FLAG_LLD_GROUP_UPDATE_NAME		__UINT64_C(0x00000002)	/* groups.name field should be updated */
166 #define ZBX_FLAG_LLD_GROUP_UPDATE		ZBX_FLAG_LLD_GROUP_UPDATE_NAME
167 	zbx_uint64_t		flags;
168 }
169 zbx_lld_group_t;
170 
lld_group_free(zbx_lld_group_t * group)171 static void	lld_group_free(zbx_lld_group_t *group)
172 {
173 	/* zbx_vector_ptr_clear_ext(&group->hosts, (zbx_clean_func_t)lld_host_free); is not missing here */
174 	zbx_vector_ptr_destroy(&group->hosts);
175 	zbx_free(group->name_proto);
176 	zbx_free(group->name);
177 	zbx_free(group->name_orig);
178 	zbx_free(group);
179 }
180 
181 typedef struct
182 {
183 	char				*name;
184 	/* permission pair (usrgrpid, permission) */
185 	zbx_vector_uint64_pair_t	rights;
186 	/* reference to the inherited rights */
187 	zbx_vector_uint64_pair_t	*prights;
188 }
189 zbx_lld_group_rights_t;
190 
191 /******************************************************************************
192  *                                                                            *
193  * Function: lld_hosts_get                                                    *
194  *                                                                            *
195  * Purpose: retrieves existing hosts for the specified host prototype         *
196  *                                                                            *
197  * Parameters: parent_hostid - [IN] host prototype identifier                 *
198  *             hosts         - [OUT] list of hosts                            *
199  *                                                                            *
200  ******************************************************************************/
lld_hosts_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts,zbx_uint64_t proxy_hostid,char ipmi_authtype,unsigned char ipmi_privilege,const char * ipmi_username,const char * ipmi_password,unsigned char tls_connect,unsigned char tls_accept,const char * tls_issuer,const char * tls_subject,const char * tls_psk_identity,const char * tls_psk)201 static void	lld_hosts_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts, zbx_uint64_t proxy_hostid,
202 		char ipmi_authtype, unsigned char ipmi_privilege, const char *ipmi_username, const char *ipmi_password,
203 		unsigned char tls_connect, unsigned char tls_accept, const char *tls_issuer,
204 		const char *tls_subject, const char *tls_psk_identity, const char *tls_psk)
205 {
206 	const char	*__function_name = "lld_hosts_get";
207 
208 	DB_RESULT	result;
209 	DB_ROW		row;
210 	zbx_lld_host_t	*host;
211 	zbx_uint64_t	db_proxy_hostid;
212 
213 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
214 
215 	result = DBselect(
216 			"select hd.hostid,hd.host,hd.lastcheck,hd.ts_delete,h.host,h.name,h.proxy_hostid,"
217 				"h.ipmi_authtype,h.ipmi_privilege,h.ipmi_username,h.ipmi_password,hi.inventory_mode,"
218 				"h.tls_connect,h.tls_accept,h.tls_issuer,h.tls_subject,h.tls_psk_identity,h.tls_psk"
219 			" from host_discovery hd"
220 				" join hosts h"
221 					" on hd.hostid=h.hostid"
222 				" left join host_inventory hi"
223 					" on hd.hostid=hi.hostid"
224 			" where hd.parent_hostid=" ZBX_FS_UI64,
225 			parent_hostid);
226 
227 	while (NULL != (row = DBfetch(result)))
228 	{
229 		host = (zbx_lld_host_t *)zbx_malloc(NULL, sizeof(zbx_lld_host_t));
230 
231 		ZBX_STR2UINT64(host->hostid, row[0]);
232 		host->host_proto = zbx_strdup(NULL, row[1]);
233 		host->lastcheck = atoi(row[2]);
234 		host->ts_delete = atoi(row[3]);
235 		host->host = zbx_strdup(NULL, row[4]);
236 		host->host_orig = NULL;
237 		host->name = zbx_strdup(NULL, row[5]);
238 		host->name_orig = NULL;
239 		host->flags = 0x00;
240 
241 		ZBX_DBROW2UINT64(db_proxy_hostid, row[6]);
242 		if (db_proxy_hostid != proxy_hostid)
243 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_PROXY;
244 
245 		if ((char)atoi(row[7]) != ipmi_authtype)
246 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH;
247 
248 		if ((unsigned char)atoi(row[8]) != ipmi_privilege)
249 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV;
250 
251 		if (0 != strcmp(row[9], ipmi_username))
252 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER;
253 
254 		if (0 != strcmp(row[10], ipmi_password))
255 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS;
256 
257 		if (atoi(row[12]) != tls_connect)
258 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT;
259 
260 		if (atoi(row[13]) != tls_accept)
261 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT;
262 
263 		if (0 != strcmp(tls_issuer, row[14]))
264 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER;
265 
266 		if (0 != strcmp(tls_subject, row[15]))
267 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT;
268 
269 		if (0 != strcmp(tls_psk_identity, row[16]))
270 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY;
271 
272 		if (0 != strcmp(tls_psk, row[17]))
273 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK;
274 
275 		if (SUCCEED == DBis_null(row[11]))
276 			host->inventory_mode = HOST_INVENTORY_DISABLED;
277 		else
278 			host->inventory_mode = (char)atoi(row[11]);
279 
280 		zbx_vector_uint64_create(&host->new_groupids);
281 		zbx_vector_uint64_create(&host->lnk_templateids);
282 		zbx_vector_uint64_create(&host->del_templateids);
283 		zbx_vector_ptr_create(&host->new_hostmacros);
284 		zbx_vector_ptr_create(&host->interfaces);
285 
286 		zbx_vector_ptr_append(hosts, host);
287 	}
288 	DBfree_result(result);
289 
290 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
291 }
292 
293 /******************************************************************************
294  *                                                                            *
295  * Function: lld_hosts_validate                                               *
296  *                                                                            *
297  * Parameters: hosts - [IN] list of hosts; should be sorted by hostid         *
298  *                                                                            *
299  ******************************************************************************/
lld_hosts_validate(zbx_vector_ptr_t * hosts,char ** error)300 static void	lld_hosts_validate(zbx_vector_ptr_t *hosts, char **error)
301 {
302 	const char		*__function_name = "lld_hosts_validate";
303 
304 	DB_RESULT		result;
305 	DB_ROW			row;
306 	int			i, j;
307 	zbx_lld_host_t		*host, *host_b;
308 	zbx_vector_uint64_t	hostids;
309 	zbx_vector_str_t	tnames, vnames;
310 
311 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
312 
313 	zbx_vector_uint64_create(&hostids);
314 	zbx_vector_str_create(&tnames);		/* list of technical host names */
315 	zbx_vector_str_create(&vnames);		/* list of visible host names */
316 
317 	/* checking a host name validity */
318 	for (i = 0; i < hosts->values_num; i++)
319 	{
320 		char	*ch_error;
321 
322 		host = (zbx_lld_host_t *)hosts->values[i];
323 
324 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
325 			continue;
326 
327 		/* only new hosts or hosts with changed host name will be validated */
328 		if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
329 			continue;
330 
331 		/* host name is valid? */
332 		if (SUCCEED == zbx_check_hostname(host->host, &ch_error))
333 			continue;
334 
335 		*error = zbx_strdcatf(*error, "Cannot %s host \"%s\": %s.\n",
336 				(0 != host->hostid ? "update" : "create"), host->host, ch_error);
337 
338 		zbx_free(ch_error);
339 
340 		if (0 != host->hostid)
341 		{
342 			lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
343 					ZBX_FLAG_LLD_HOST_UPDATE_HOST);
344 		}
345 		else
346 			host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
347 	}
348 
349 	/* checking a visible host name validity */
350 	for (i = 0; i < hosts->values_num; i++)
351 	{
352 		host = (zbx_lld_host_t *)hosts->values[i];
353 
354 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
355 			continue;
356 
357 		/* only new hosts or hosts with changed visible name will be validated */
358 		if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
359 			continue;
360 
361 		/* visible host name is valid utf8 sequence and has a valid length */
362 		if (SUCCEED == zbx_is_utf8(host->name) && '\0' != *host->name &&
363 				HOST_NAME_LEN >= zbx_strlen_utf8(host->name))
364 		{
365 			continue;
366 		}
367 
368 		zbx_replace_invalid_utf8(host->name);
369 		*error = zbx_strdcatf(*error, "Cannot %s host: invalid visible host name \"%s\".\n",
370 				(0 != host->hostid ? "update" : "create"), host->name);
371 
372 		if (0 != host->hostid)
373 		{
374 			lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
375 					ZBX_FLAG_LLD_HOST_UPDATE_NAME);
376 		}
377 		else
378 			host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
379 	}
380 
381 	/* checking duplicated host names */
382 	for (i = 0; i < hosts->values_num; i++)
383 	{
384 		host = (zbx_lld_host_t *)hosts->values[i];
385 
386 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
387 			continue;
388 
389 		/* only new hosts or hosts with changed host name will be validated */
390 		if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
391 			continue;
392 
393 		for (j = 0; j < hosts->values_num; j++)
394 		{
395 			host_b = (zbx_lld_host_t *)hosts->values[j];
396 
397 			if (0 == (host_b->flags & ZBX_FLAG_LLD_HOST_DISCOVERED) || i == j)
398 				continue;
399 
400 			if (0 != strcmp(host->host, host_b->host))
401 				continue;
402 
403 			*error = zbx_strdcatf(*error, "Cannot %s host:"
404 					" host with the same name \"%s\" already exists.\n",
405 					(0 != host->hostid ? "update" : "create"), host->host);
406 
407 			if (0 != host->hostid)
408 			{
409 				lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
410 						ZBX_FLAG_LLD_HOST_UPDATE_HOST);
411 			}
412 			else
413 				host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
414 		}
415 	}
416 
417 	/* checking duplicated visible host names */
418 	for (i = 0; i < hosts->values_num; i++)
419 	{
420 		host = (zbx_lld_host_t *)hosts->values[i];
421 
422 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
423 			continue;
424 
425 		/* only new hosts or hosts with changed visible name will be validated */
426 		if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
427 			continue;
428 
429 		for (j = 0; j < hosts->values_num; j++)
430 		{
431 			host_b = (zbx_lld_host_t *)hosts->values[j];
432 
433 			if (0 == (host_b->flags & ZBX_FLAG_LLD_HOST_DISCOVERED) || i == j)
434 				continue;
435 
436 			if (0 != strcmp(host->name, host_b->name))
437 				continue;
438 
439 			*error = zbx_strdcatf(*error, "Cannot %s host:"
440 					" host with the same visible name \"%s\" already exists.\n",
441 					(0 != host->hostid ? "update" : "create"), host->name);
442 
443 			if (0 != host->hostid)
444 			{
445 				lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
446 						ZBX_FLAG_LLD_HOST_UPDATE_NAME);
447 			}
448 			else
449 				host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
450 		}
451 	}
452 
453 	/* checking duplicated host names and visible host names in DB */
454 
455 	for (i = 0; i < hosts->values_num; i++)
456 	{
457 		host = (zbx_lld_host_t *)hosts->values[i];
458 
459 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
460 			continue;
461 
462 		if (0 != host->hostid)
463 			zbx_vector_uint64_append(&hostids, host->hostid);
464 
465 		if (0 == host->hostid || 0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
466 			zbx_vector_str_append(&tnames, host->host);
467 
468 		if (0 == host->hostid || 0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
469 			zbx_vector_str_append(&vnames, host->name);
470 	}
471 
472 	if (0 != tnames.values_num || 0 != vnames.values_num)
473 	{
474 		char	*sql = NULL;
475 		size_t	sql_alloc = 0, sql_offset = 0;
476 
477 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
478 				"select host,name"
479 				" from hosts"
480 				" where status in (%d,%d,%d)"
481 					" and flags<>%d"
482 					" and",
483 				HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, HOST_STATUS_TEMPLATE,
484 				ZBX_FLAG_DISCOVERY_PROTOTYPE);
485 
486 		if (0 != tnames.values_num && 0 != vnames.values_num)
487 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " (");
488 
489 		if (0 != tnames.values_num)
490 		{
491 			DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "host",
492 					(const char **)tnames.values, tnames.values_num);
493 		}
494 
495 		if (0 != tnames.values_num && 0 != vnames.values_num)
496 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " or");
497 
498 		if (0 != vnames.values_num)
499 		{
500 			DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
501 					(const char **)vnames.values, vnames.values_num);
502 		}
503 
504 		if (0 != tnames.values_num && 0 != vnames.values_num)
505 			zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ')');
506 
507 		if (0 != hostids.values_num)
508 		{
509 			zbx_vector_uint64_sort(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
510 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
511 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
512 					hostids.values, hostids.values_num);
513 		}
514 
515 		result = DBselect("%s", sql);
516 
517 		while (NULL != (row = DBfetch(result)))
518 		{
519 			for (i = 0; i < hosts->values_num; i++)
520 			{
521 				host = (zbx_lld_host_t *)hosts->values[i];
522 
523 				if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
524 					continue;
525 
526 				if (0 == strcmp(host->host, row[0]))
527 				{
528 					*error = zbx_strdcatf(*error, "Cannot %s host:"
529 							" host with the same name \"%s\" already exists.\n",
530 							(0 != host->hostid ? "update" : "create"), host->host);
531 
532 					if (0 != host->hostid)
533 					{
534 						lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
535 								ZBX_FLAG_LLD_HOST_UPDATE_HOST);
536 					}
537 					else
538 						host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
539 				}
540 
541 				if (0 == strcmp(host->name, row[1]))
542 				{
543 					*error = zbx_strdcatf(*error, "Cannot %s host:"
544 							" host with the same visible name \"%s\" already exists.\n",
545 							(0 != host->hostid ? "update" : "create"), host->name);
546 
547 					if (0 != host->hostid)
548 					{
549 						lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
550 								ZBX_FLAG_LLD_HOST_UPDATE_NAME);
551 					}
552 					else
553 						host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
554 				}
555 			}
556 		}
557 		DBfree_result(result);
558 
559 		zbx_free(sql);
560 	}
561 
562 	zbx_vector_str_destroy(&vnames);
563 	zbx_vector_str_destroy(&tnames);
564 	zbx_vector_uint64_destroy(&hostids);
565 
566 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
567 }
568 
lld_host_make(zbx_vector_ptr_t * hosts,const char * host_proto,const char * name_proto,const struct zbx_json_parse * jp_row)569 static zbx_lld_host_t	*lld_host_make(zbx_vector_ptr_t *hosts, const char *host_proto, const char *name_proto,
570 		const struct zbx_json_parse *jp_row)
571 {
572 	const char	*__function_name = "lld_host_make";
573 
574 	char		*buffer = NULL;
575 	int		i;
576 	zbx_lld_host_t	*host = NULL;
577 
578 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
579 
580 	for (i = 0; i < hosts->values_num; i++)
581 	{
582 		host = (zbx_lld_host_t *)hosts->values[i];
583 
584 		if (0 != (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
585 			continue;
586 
587 		buffer = zbx_strdup(buffer, host->host_proto);
588 		substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
589 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
590 
591 		if (0 == strcmp(host->host, buffer))
592 			break;
593 	}
594 
595 	if (i == hosts->values_num)	/* no host found */
596 	{
597 		host = (zbx_lld_host_t *)zbx_malloc(NULL, sizeof(zbx_lld_host_t));
598 
599 		host->hostid = 0;
600 		host->host_proto = NULL;
601 		host->lastcheck = 0;
602 		host->ts_delete = 0;
603 		host->host = zbx_strdup(NULL, host_proto);
604 		host->host_orig = NULL;
605 		substitute_lld_macros(&host->host, jp_row, ZBX_MACRO_ANY, NULL, 0);
606 		zbx_lrtrim(host->host, ZBX_WHITESPACE);
607 		host->name = zbx_strdup(NULL, name_proto);
608 		substitute_lld_macros(&host->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
609 		zbx_lrtrim(host->name, ZBX_WHITESPACE);
610 		host->name_orig = NULL;
611 		zbx_vector_uint64_create(&host->new_groupids);
612 		zbx_vector_uint64_create(&host->lnk_templateids);
613 		zbx_vector_uint64_create(&host->del_templateids);
614 		zbx_vector_ptr_create(&host->new_hostmacros);
615 		zbx_vector_ptr_create(&host->interfaces);
616 		host->flags = ZBX_FLAG_LLD_HOST_DISCOVERED;
617 
618 		zbx_vector_ptr_append(hosts, host);
619 	}
620 	else
621 	{
622 		/* host technical name */
623 		if (0 != strcmp(host->host_proto, host_proto))	/* the new host prototype differs */
624 		{
625 			host->host_orig = host->host;
626 			host->host = zbx_strdup(NULL, host_proto);
627 			substitute_lld_macros(&host->host, jp_row, ZBX_MACRO_ANY, NULL, 0);
628 			zbx_lrtrim(host->host, ZBX_WHITESPACE);
629 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_HOST;
630 		}
631 
632 		/* host visible name */
633 		buffer = zbx_strdup(buffer, name_proto);
634 		substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
635 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
636 		if (0 != strcmp(host->name, buffer))
637 		{
638 			host->name_orig = host->name;
639 			host->name = buffer;
640 			buffer = NULL;
641 			host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_NAME;
642 		}
643 
644 		host->flags |= ZBX_FLAG_LLD_HOST_DISCOVERED;
645 	}
646 
647 	zbx_free(buffer);
648 
649 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, (void *)host);
650 
651 	return host;
652 }
653 
654 /******************************************************************************
655  *                                                                            *
656  * Function: lld_simple_groups_get                                            *
657  *                                                                            *
658  * Purpose: retrieve list of host groups which should be present on the each  *
659  *          discovered host                                                   *
660  *                                                                            *
661  * Parameters: parent_hostid - [IN] host prototype identifier                 *
662  *             groupids      - [OUT] sorted list of host groups               *
663  *                                                                            *
664  ******************************************************************************/
lld_simple_groups_get(zbx_uint64_t parent_hostid,zbx_vector_uint64_t * groupids)665 static void	lld_simple_groups_get(zbx_uint64_t parent_hostid, zbx_vector_uint64_t *groupids)
666 {
667 	DB_RESULT	result;
668 	DB_ROW		row;
669 	zbx_uint64_t	groupid;
670 
671 	result = DBselect(
672 			"select groupid"
673 			" from group_prototype"
674 			" where groupid is not null"
675 				" and hostid=" ZBX_FS_UI64,
676 			parent_hostid);
677 
678 	while (NULL != (row = DBfetch(result)))
679 	{
680 		ZBX_STR2UINT64(groupid, row[0]);
681 		zbx_vector_uint64_append(groupids, groupid);
682 	}
683 	DBfree_result(result);
684 
685 	zbx_vector_uint64_sort(groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
686 }
687 
688 /******************************************************************************
689  *                                                                            *
690  * Function: lld_hostgroups_make                                              *
691  *                                                                            *
692  * Parameters: groupids         - [IN] sorted list of host group ids which    *
693  *                                     should be present on the each          *
694  *                                     discovered host (Groups)               *
695  *             hosts            - [IN/OUT] list of hosts                      *
696  *                                         should be sorted by hostid         *
697  *             groups           - [IN]  list of host groups (Group prototypes)*
698  *             del_hostgroupids - [OUT] sorted list of host groups which      *
699  *                                      should be deleted                     *
700  *                                                                            *
701  ******************************************************************************/
lld_hostgroups_make(const zbx_vector_uint64_t * groupids,zbx_vector_ptr_t * hosts,const zbx_vector_ptr_t * groups,zbx_vector_uint64_t * del_hostgroupids)702 static void	lld_hostgroups_make(const zbx_vector_uint64_t *groupids, zbx_vector_ptr_t *hosts,
703 		const zbx_vector_ptr_t *groups, zbx_vector_uint64_t *del_hostgroupids)
704 {
705 	const char		*__function_name = "lld_hostgroups_make";
706 
707 	DB_RESULT		result;
708 	DB_ROW			row;
709 	int			i, j;
710 	zbx_vector_uint64_t	hostids;
711 	zbx_uint64_t		hostgroupid, hostid, groupid;
712 	zbx_lld_host_t		*host;
713 	const zbx_lld_group_t	*group;
714 
715 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
716 
717 	zbx_vector_uint64_create(&hostids);
718 
719 	for (i = 0; i < hosts->values_num; i++)
720 	{
721 		host = (zbx_lld_host_t *)hosts->values[i];
722 
723 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
724 			continue;
725 
726 		zbx_vector_uint64_reserve(&host->new_groupids, groupids->values_num);
727 		for (j = 0; j < groupids->values_num; j++)
728 			zbx_vector_uint64_append(&host->new_groupids, groupids->values[j]);
729 
730 		if (0 != host->hostid)
731 			zbx_vector_uint64_append(&hostids, host->hostid);
732 	}
733 
734 	for (i = 0; i < groups->values_num; i++)
735 	{
736 		group = (zbx_lld_group_t *)groups->values[i];
737 
738 		if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED) || 0 == group->groupid)
739 			continue;
740 
741 		for (j = 0; j < group->hosts.values_num; j++)
742 		{
743 			host = (zbx_lld_host_t *)group->hosts.values[j];
744 
745 			zbx_vector_uint64_append(&host->new_groupids, group->groupid);
746 		}
747 	}
748 
749 	for (i = 0; i < hosts->values_num; i++)
750 	{
751 		host = (zbx_lld_host_t *)hosts->values[i];
752 		zbx_vector_uint64_sort(&host->new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
753 	}
754 
755 	if (0 != hostids.values_num)
756 	{
757 		char	*sql = NULL;
758 		size_t	sql_alloc = 0, sql_offset = 0;
759 
760 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
761 				"select hostid,groupid,hostgroupid"
762 				" from hosts_groups"
763 				" where");
764 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
765 
766 		result = DBselect("%s", sql);
767 
768 		zbx_free(sql);
769 
770 		while (NULL != (row = DBfetch(result)))
771 		{
772 			ZBX_STR2UINT64(hostid, row[0]);
773 			ZBX_STR2UINT64(groupid, row[1]);
774 
775 			if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
776 			{
777 				THIS_SHOULD_NEVER_HAPPEN;
778 				continue;
779 			}
780 
781 			host = (zbx_lld_host_t *)hosts->values[i];
782 
783 			if (FAIL == (i = zbx_vector_uint64_bsearch(&host->new_groupids, groupid,
784 					ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
785 			{
786 				/* host groups which should be unlinked */
787 				ZBX_STR2UINT64(hostgroupid, row[2]);
788 				zbx_vector_uint64_append(del_hostgroupids, hostgroupid);
789 			}
790 			else
791 			{
792 				/* host groups which are already added */
793 				zbx_vector_uint64_remove(&host->new_groupids, i);
794 			}
795 		}
796 		DBfree_result(result);
797 
798 		zbx_vector_uint64_sort(del_hostgroupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
799 	}
800 
801 	zbx_vector_uint64_destroy(&hostids);
802 
803 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
804 }
805 
806 /******************************************************************************
807  *                                                                            *
808  * Function: lld_group_prototypes_get                                         *
809  *                                                                            *
810  * Purpose: retrieve list of group prototypes                                 *
811  *                                                                            *
812  * Parameters: parent_hostid    - [IN] host prototype identifier              *
813  *             group_prototypes - [OUT] sorted list of group prototypes       *
814  *                                                                            *
815  ******************************************************************************/
lld_group_prototypes_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * group_prototypes)816 static void	lld_group_prototypes_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *group_prototypes)
817 {
818 	const char			*__function_name = "lld_group_prototypes_get";
819 
820 	DB_RESULT			result;
821 	DB_ROW				row;
822 	zbx_lld_group_prototype_t	*group_prototype;
823 
824 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
825 
826 	result = DBselect(
827 			"select group_prototypeid,name"
828 			" from group_prototype"
829 			" where groupid is null"
830 				" and hostid=" ZBX_FS_UI64,
831 			parent_hostid);
832 
833 	while (NULL != (row = DBfetch(result)))
834 	{
835 		group_prototype = (zbx_lld_group_prototype_t *)zbx_malloc(NULL, sizeof(zbx_lld_group_prototype_t));
836 
837 		ZBX_STR2UINT64(group_prototype->group_prototypeid, row[0]);
838 		group_prototype->name = zbx_strdup(NULL, row[1]);
839 
840 		zbx_vector_ptr_append(group_prototypes, group_prototype);
841 	}
842 	DBfree_result(result);
843 
844 	zbx_vector_ptr_sort(group_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
845 
846 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
847 }
848 
849 /******************************************************************************
850  *                                                                            *
851  * Function: lld_groups_get                                                   *
852  *                                                                            *
853  * Purpose: retrieves existing groups for the specified host prototype        *
854  *                                                                            *
855  * Parameters: parent_hostid - [IN] host prototype identifier                 *
856  *             groups        - [OUT] list of groups                           *
857  *                                                                            *
858  ******************************************************************************/
lld_groups_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * groups)859 static void	lld_groups_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *groups)
860 {
861 	const char	*__function_name = "lld_groups_get";
862 
863 	DB_RESULT	result;
864 	DB_ROW		row;
865 	zbx_lld_group_t	*group;
866 
867 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
868 
869 	result = DBselect(
870 			"select gd.groupid,gp.group_prototypeid,gd.name,gd.lastcheck,gd.ts_delete,g.name"
871 			" from group_prototype gp,group_discovery gd"
872 				" join hstgrp g"
873 					" on gd.groupid=g.groupid"
874 			" where gp.group_prototypeid=gd.parent_group_prototypeid"
875 				" and gp.hostid=" ZBX_FS_UI64,
876 			parent_hostid);
877 
878 	while (NULL != (row = DBfetch(result)))
879 	{
880 		group = (zbx_lld_group_t *)zbx_malloc(NULL, sizeof(zbx_lld_group_t));
881 
882 		ZBX_STR2UINT64(group->groupid, row[0]);
883 		ZBX_STR2UINT64(group->group_prototypeid, row[1]);
884 		zbx_vector_ptr_create(&group->hosts);
885 		group->name_proto = zbx_strdup(NULL, row[2]);
886 		group->lastcheck = atoi(row[3]);
887 		group->ts_delete = atoi(row[4]);
888 		group->name = zbx_strdup(NULL, row[5]);
889 		group->name_orig = NULL;
890 		group->flags = 0x00;
891 
892 		zbx_vector_ptr_append(groups, group);
893 	}
894 	DBfree_result(result);
895 
896 	zbx_vector_ptr_sort(groups, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
897 
898 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
899 }
900 
901 /******************************************************************************
902  *                                                                            *
903  * Function: lld_group_make                                                   *
904  *                                                                            *
905  ******************************************************************************/
lld_group_make(zbx_vector_ptr_t * groups,zbx_uint64_t group_prototypeid,const char * name_proto,const struct zbx_json_parse * jp_row)906 static zbx_lld_group_t	*lld_group_make(zbx_vector_ptr_t *groups, zbx_uint64_t group_prototypeid,
907 		const char *name_proto, const struct zbx_json_parse *jp_row)
908 {
909 	const char	*__function_name = "lld_group_make";
910 
911 	char		*buffer = NULL;
912 	int		i;
913 	zbx_lld_group_t	*group = NULL;
914 
915 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
916 
917 	for (i = 0; i < groups->values_num; i++)
918 	{
919 		group = (zbx_lld_group_t *)groups->values[i];
920 
921 		if (group->group_prototypeid != group_prototypeid)
922 			continue;
923 
924 		if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
925 			continue;
926 
927 		buffer = zbx_strdup(buffer, group->name_proto);
928 		substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
929 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
930 
931 		if (0 == strcmp(group->name, buffer))
932 			break;
933 	}
934 
935 	if (i == groups->values_num)	/* no group found */
936 	{
937 		/* trying to find an already existing group */
938 
939 		buffer = zbx_strdup(buffer, name_proto);
940 		substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
941 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
942 
943 		for (i = 0; i < groups->values_num; i++)
944 		{
945 			group = (zbx_lld_group_t *)groups->values[i];
946 
947 			if (group->group_prototypeid != group_prototypeid)
948 				continue;
949 
950 			if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
951 				continue;
952 
953 			if (0 == strcmp(group->name, buffer))
954 				goto out;
955 		}
956 
957 		/* otherwise create a new group */
958 
959 		group = (zbx_lld_group_t *)zbx_malloc(NULL, sizeof(zbx_lld_group_t));
960 
961 		group->groupid = 0;
962 		group->group_prototypeid = group_prototypeid;
963 		zbx_vector_ptr_create(&group->hosts);
964 		group->name_proto = NULL;
965 		group->name = zbx_strdup(NULL, name_proto);
966 		substitute_lld_macros(&group->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
967 		zbx_lrtrim(group->name, ZBX_WHITESPACE);
968 		group->name_orig = NULL;
969 		group->lastcheck = 0;
970 		group->ts_delete = 0;
971 		group->flags = 0x00;
972 		group->flags = ZBX_FLAG_LLD_GROUP_DISCOVERED;
973 
974 		zbx_vector_ptr_append(groups, group);
975 	}
976 	else
977 	{
978 		/* update an already existing group */
979 
980 		/* group name */
981 		buffer = zbx_strdup(buffer, name_proto);
982 		substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
983 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
984 		if (0 != strcmp(group->name, buffer))
985 		{
986 			group->name_orig = group->name;
987 			group->name = buffer;
988 			buffer = NULL;
989 			group->flags |= ZBX_FLAG_LLD_GROUP_UPDATE_NAME;
990 		}
991 
992 		group->flags |= ZBX_FLAG_LLD_GROUP_DISCOVERED;
993 	}
994 out:
995 	zbx_free(buffer);
996 
997 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, (void *)group);
998 
999 	return group;
1000 }
1001 
1002 /******************************************************************************
1003  *                                                                            *
1004  * Function: lld_groups_make                                                  *
1005  *                                                                            *
1006  ******************************************************************************/
lld_groups_make(zbx_lld_host_t * host,zbx_vector_ptr_t * groups,const zbx_vector_ptr_t * group_prototypes,const struct zbx_json_parse * jp_row)1007 static void	lld_groups_make(zbx_lld_host_t *host, zbx_vector_ptr_t *groups, const zbx_vector_ptr_t *group_prototypes,
1008 		const struct zbx_json_parse *jp_row)
1009 {
1010 	const char	*__function_name = "lld_groups_make";
1011 
1012 	int		i;
1013 
1014 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1015 
1016 	for (i = 0; i < group_prototypes->values_num; i++)
1017 	{
1018 		const zbx_lld_group_prototype_t	*group_prototype;
1019 		zbx_lld_group_t			*group;
1020 
1021 		group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[i];
1022 
1023 		group = lld_group_make(groups, group_prototype->group_prototypeid, group_prototype->name, jp_row);
1024 
1025 		zbx_vector_ptr_append(&group->hosts, host);
1026 	}
1027 
1028 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1029 }
1030 
1031 /******************************************************************************
1032  *                                                                            *
1033  * Function: lld_validate_group_name                                          *
1034  *                                                                            *
1035  * Purpose: validate group name                                               *
1036  *                                                                            *
1037  * Return value: SUCCEED - the group name is valid                            *
1038  *               FAIL    - otherwise                                          *
1039  *                                                                            *
1040  ******************************************************************************/
lld_validate_group_name(const char * name)1041 static int	lld_validate_group_name(const char *name)
1042 {
1043 	/* group name cannot be empty */
1044 	if ('\0' == *name)
1045 		return FAIL;
1046 
1047 	/* group name must contain valid utf8 characters */
1048 	if (SUCCEED != zbx_is_utf8(name))
1049 		return FAIL;
1050 
1051 	/* group name cannot exceed field limits */
1052 	if (GROUP_NAME_LEN < zbx_strlen_utf8(name))
1053 		return FAIL;
1054 
1055 	/* group name cannot contain trailing and leading slashes (/) */
1056 	if ('/' == *name || '/' == name[strlen(name) - 1])
1057 		return FAIL;
1058 
1059 	/* group name cannot contain several slashes (/) in a row */
1060 	if (NULL != strstr(name, "//"))
1061 		return FAIL;
1062 
1063 	return SUCCEED;
1064 }
1065 
1066 /******************************************************************************
1067  *                                                                            *
1068  * Function: lld_groups_validate                                              *
1069  *                                                                            *
1070  * Parameters: groups - [IN] list of groups; should be sorted by groupid      *
1071  *                                                                            *
1072  ******************************************************************************/
lld_groups_validate(zbx_vector_ptr_t * groups,char ** error)1073 static void	lld_groups_validate(zbx_vector_ptr_t *groups, char **error)
1074 {
1075 	const char		*__function_name = "lld_groups_validate";
1076 
1077 	DB_RESULT		result;
1078 	DB_ROW			row;
1079 	int			i, j;
1080 	zbx_lld_group_t		*group, *group_b;
1081 	zbx_vector_uint64_t	groupids;
1082 	zbx_vector_str_t	names;
1083 
1084 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1085 
1086 	zbx_vector_uint64_create(&groupids);
1087 	zbx_vector_str_create(&names);		/* list of group names */
1088 
1089 	/* checking a group name validity */
1090 	for (i = 0; i < groups->values_num; i++)
1091 	{
1092 		group = (zbx_lld_group_t *)groups->values[i];
1093 
1094 		if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1095 			continue;
1096 
1097 		/* only new groups or groups with changed group name will be validated */
1098 		if (0 != group->groupid && 0 == (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1099 			continue;
1100 
1101 		if (SUCCEED == lld_validate_group_name(group->name))
1102 			continue;
1103 
1104 		zbx_replace_invalid_utf8(group->name);
1105 		*error = zbx_strdcatf(*error, "Cannot %s group: invalid group name \"%s\".\n",
1106 				(0 != group->groupid ? "update" : "create"), group->name);
1107 
1108 		if (0 != group->groupid)
1109 		{
1110 			lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1111 					ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1112 		}
1113 		else
1114 			group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1115 	}
1116 
1117 	/* checking duplicated group names */
1118 	for (i = 0; i < groups->values_num; i++)
1119 	{
1120 		group = (zbx_lld_group_t *)groups->values[i];
1121 
1122 		if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1123 			continue;
1124 
1125 		/* only new groups or groups with changed group name will be validated */
1126 		if (0 != group->groupid && 0 == (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1127 			continue;
1128 
1129 		for (j = 0; j < groups->values_num; j++)
1130 		{
1131 			group_b = (zbx_lld_group_t *)groups->values[j];
1132 
1133 			if (0 == (group_b->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED) || i == j)
1134 				continue;
1135 
1136 			if (0 != strcmp(group->name, group_b->name))
1137 				continue;
1138 
1139 			*error = zbx_strdcatf(*error, "Cannot %s group:"
1140 					" group with the same name \"%s\" already exists.\n",
1141 					(0 != group->groupid ? "update" : "create"), group->name);
1142 
1143 			if (0 != group->groupid)
1144 			{
1145 				lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1146 						ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1147 			}
1148 			else
1149 				group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1150 		}
1151 	}
1152 
1153 	/* checking duplicated group names and group names in DB */
1154 
1155 	for (i = 0; i < groups->values_num; i++)
1156 	{
1157 		group = (zbx_lld_group_t *)groups->values[i];
1158 
1159 		if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1160 			continue;
1161 
1162 		if (0 != group->groupid)
1163 			zbx_vector_uint64_append(&groupids, group->groupid);
1164 
1165 		if (0 == group->groupid || 0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1166 			zbx_vector_str_append(&names, group->name);
1167 	}
1168 
1169 	if (0 != names.values_num)
1170 	{
1171 		char	*sql = NULL;
1172 		size_t	sql_alloc = 0, sql_offset = 0;
1173 
1174 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select name from hstgrp where");
1175 		DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
1176 				(const char **)names.values, names.values_num);
1177 
1178 		if (0 != groupids.values_num)
1179 		{
1180 			zbx_vector_uint64_sort(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1181 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
1182 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
1183 					groupids.values, groupids.values_num);
1184 		}
1185 
1186 		result = DBselect("%s", sql);
1187 
1188 		while (NULL != (row = DBfetch(result)))
1189 		{
1190 			for (i = 0; i < groups->values_num; i++)
1191 			{
1192 				group = (zbx_lld_group_t *)groups->values[i];
1193 
1194 				if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1195 					continue;
1196 
1197 				if (0 == strcmp(group->name, row[0]))
1198 				{
1199 					*error = zbx_strdcatf(*error, "Cannot %s group:"
1200 							" group with the same name \"%s\" already exists.\n",
1201 							(0 != group->groupid ? "update" : "create"), group->name);
1202 
1203 					if (0 != group->groupid)
1204 					{
1205 						lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1206 								ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1207 					}
1208 					else
1209 						group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1210 				}
1211 			}
1212 		}
1213 		DBfree_result(result);
1214 
1215 		zbx_free(sql);
1216 	}
1217 
1218 	zbx_vector_str_destroy(&names);
1219 	zbx_vector_uint64_destroy(&groupids);
1220 
1221 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1222 }
1223 
1224 /******************************************************************************
1225  *                                                                            *
1226  * Function: lld_group_rights_compare                                         *
1227  *                                                                            *
1228  * Purpose: sorting function to sort group rights vector by name              *
1229  *                                                                            *
1230  ******************************************************************************/
lld_group_rights_compare(const void * d1,const void * d2)1231 static int	lld_group_rights_compare(const void *d1, const void *d2)
1232 {
1233 	const zbx_lld_group_rights_t	*r1 = *(const zbx_lld_group_rights_t **)d1;
1234 	const zbx_lld_group_rights_t	*r2 = *(const zbx_lld_group_rights_t **)d2;
1235 
1236 	return strcmp(r1->name, r2->name);
1237 }
1238 
1239 /******************************************************************************
1240  *                                                                            *
1241  * Function: lld_group_rights_append                                          *
1242  *                                                                            *
1243  * Purpose: append a new item to group rights vector                          *
1244  *                                                                            *
1245  * Return value: Index of the added item.                                     *
1246  *                                                                            *
1247  ******************************************************************************/
lld_group_rights_append(zbx_vector_ptr_t * group_rights,const char * name)1248 static int	lld_group_rights_append(zbx_vector_ptr_t *group_rights, const char *name)
1249 {
1250 	zbx_lld_group_rights_t	*rights;
1251 
1252 	rights = (zbx_lld_group_rights_t *)zbx_malloc(NULL, sizeof(zbx_lld_group_rights_t));
1253 	rights->name = zbx_strdup(NULL, name);
1254 	zbx_vector_uint64_pair_create(&rights->rights);
1255 	rights->prights = NULL;
1256 
1257 	zbx_vector_ptr_append(group_rights, rights);
1258 
1259 	return group_rights->values_num - 1;
1260 }
1261 
1262 /******************************************************************************
1263  *                                                                            *
1264  * Function: lld_group_rights_free                                            *
1265  *                                                                            *
1266  * PUrpose: frees group rights data                                           *
1267  *                                                                            *
1268  ******************************************************************************/
lld_group_rights_free(zbx_lld_group_rights_t * rights)1269 static void	lld_group_rights_free(zbx_lld_group_rights_t *rights)
1270 {
1271 	zbx_free(rights->name);
1272 	zbx_vector_uint64_pair_destroy(&rights->rights);
1273 	zbx_free(rights);
1274 }
1275 
1276 /******************************************************************************
1277  *                                                                            *
1278  * Function: lld_groups_save_rights                                           *
1279  *                                                                            *
1280  * Parameters: groups - [IN] list of new groups                               *
1281  *                                                                            *
1282  ******************************************************************************/
lld_groups_save_rights(zbx_vector_ptr_t * groups)1283 static void	lld_groups_save_rights(zbx_vector_ptr_t *groups)
1284 {
1285 	const char		*__function_name = "lld_groups_save_rights";
1286 
1287 	int			i, j;
1288 	DB_ROW			row;
1289 	DB_RESULT		result;
1290 	char			*ptr, *name, *sql = NULL;
1291 	size_t			sql_alloc = 0, sql_offset = 0, offset;
1292 	zbx_lld_group_t		*group;
1293 	zbx_vector_str_t	group_names;
1294 	zbx_vector_ptr_t	group_rights;
1295 	zbx_db_insert_t		db_insert;
1296 	zbx_lld_group_rights_t	*rights, rights_local, *parent_rights;
1297 	zbx_uint64_pair_t	pair;
1298 
1299 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1300 
1301 	zbx_vector_str_create(&group_names);
1302 	zbx_vector_ptr_create(&group_rights);
1303 
1304 	/* make a list of direct parent group names and a list of new group rights */
1305 	for (i = 0; i < groups->values_num; i++)
1306 	{
1307 		group = (zbx_lld_group_t *)groups->values[i];
1308 
1309 		if (NULL == (ptr = strrchr(group->name, '/')))
1310 			continue;
1311 
1312 		lld_group_rights_append(&group_rights, group->name);
1313 
1314 		name = zbx_strdup(NULL, group->name);
1315 		name[ptr - group->name] = '\0';
1316 
1317 		if (FAIL != zbx_vector_str_search(&group_names, name, ZBX_DEFAULT_STR_COMPARE_FUNC))
1318 		{
1319 			zbx_free(name);
1320 			continue;
1321 		}
1322 
1323 		zbx_vector_str_append(&group_names, name);
1324 	}
1325 
1326 	if (0 == group_names.values_num)
1327 		goto out;
1328 
1329 	/* read the parent group rights */
1330 
1331 	zbx_db_insert_prepare(&db_insert, "rights", "rightid", "id", "permission", "groupid", NULL);
1332 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1333 			"select g.name,r.permission,r.groupid from hstgrp g,rights r"
1334 				" where r.id=g.groupid"
1335 				" and");
1336 
1337 	DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "g.name", (const char **)group_names.values,
1338 			group_names.values_num);
1339 	result = DBselect("%s", sql);
1340 
1341 	while (NULL != (row = DBfetch(result)))
1342 	{
1343 		rights_local.name = row[0];
1344 		if (FAIL == (i = zbx_vector_ptr_search(&group_rights, &rights_local, lld_group_rights_compare)))
1345 			i = lld_group_rights_append(&group_rights, row[0]);
1346 
1347 		rights = (zbx_lld_group_rights_t *)group_rights.values[i];
1348 		rights->prights = &rights->rights;
1349 
1350 		ZBX_STR2UINT64(pair.first, row[2]);
1351 		pair.second = atoi(row[1]);
1352 
1353 		zbx_vector_uint64_pair_append(&rights->rights, pair);
1354 	}
1355 	DBfree_result(result);
1356 
1357 	zbx_vector_ptr_sort(&group_rights, lld_group_rights_compare);
1358 
1359 	/* assign rights for the new groups */
1360 	for (i = 0; i < group_rights.values_num; i++)
1361 	{
1362 		rights = (zbx_lld_group_rights_t *)group_rights.values[i];
1363 
1364 		if (NULL != rights->prights)
1365 			continue;
1366 
1367 		if (NULL == (ptr = strrchr(rights->name, '/')))
1368 			continue;
1369 
1370 		offset = ptr - rights->name;
1371 
1372 		for (j = 0; j < i; j++)
1373 		{
1374 			parent_rights = (zbx_lld_group_rights_t *)group_rights.values[j];
1375 
1376 			if (strlen(parent_rights->name) != offset)
1377 				continue;
1378 
1379 			if (0 != strncmp(parent_rights->name, rights->name, offset))
1380 				continue;
1381 
1382 			rights->prights = parent_rights->prights;
1383 			break;
1384 		}
1385 	}
1386 
1387 	/* save rights for the new groups */
1388 	for (i = 0; i < groups->values_num; i++)
1389 	{
1390 		group = (zbx_lld_group_t *)groups->values[i];
1391 
1392 		rights_local.name = group->name;
1393 		if (FAIL == (j = zbx_vector_ptr_bsearch(&group_rights, &rights_local, lld_group_rights_compare)))
1394 			continue;
1395 
1396 		rights = (zbx_lld_group_rights_t *)group_rights.values[j];
1397 
1398 		if (NULL == rights->prights)
1399 			continue;
1400 
1401 		for (j = 0; j < rights->prights->values_num; j++)
1402 		{
1403 			zbx_db_insert_add_values(&db_insert, __UINT64_C(0), group->groupid,
1404 					(int)rights->prights->values[j].second, rights->prights->values[j].first);
1405 		}
1406 	}
1407 
1408 	zbx_db_insert_autoincrement(&db_insert, "rightid");
1409 	zbx_db_insert_execute(&db_insert);
1410 	zbx_db_insert_clean(&db_insert);
1411 
1412 	zbx_free(sql);
1413 	zbx_vector_ptr_clear_ext(&group_rights, (zbx_clean_func_t)lld_group_rights_free);
1414 	zbx_vector_str_clear_ext(&group_names, zbx_str_free);
1415 out:
1416 	zbx_vector_ptr_destroy(&group_rights);
1417 	zbx_vector_str_destroy(&group_names);
1418 
1419 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1420 }
1421 
1422 /******************************************************************************
1423  *                                                                            *
1424  * Function: lld_groups_save                                                  *
1425  *                                                                            *
1426  * Parameters: groups           - [IN/OUT] list of groups; should be sorted   *
1427  *                                         by groupid                         *
1428  *             group_prototypes - [IN] list of group prototypes; should be    *
1429  *                                     sorted by group_prototypeid            *
1430  *                                                                            *
1431  ******************************************************************************/
lld_groups_save(zbx_vector_ptr_t * groups,const zbx_vector_ptr_t * group_prototypes)1432 static void	lld_groups_save(zbx_vector_ptr_t *groups, const zbx_vector_ptr_t *group_prototypes)
1433 {
1434 	const char			*__function_name = "lld_groups_save";
1435 
1436 	int				i, j, upd_groups_num = 0;
1437 	zbx_lld_group_t			*group;
1438 	const zbx_lld_group_prototype_t	*group_prototype;
1439 	zbx_lld_host_t			*host;
1440 	zbx_uint64_t			groupid = 0;
1441 	char				*sql = NULL, *name_esc, *name_proto_esc;
1442 	size_t				sql_alloc = 0, sql_offset = 0;
1443 	zbx_db_insert_t			db_insert, db_insert_gdiscovery;
1444 	zbx_vector_ptr_t		new_groups;
1445 	zbx_vector_uint64_t		new_group_prototype_ids;
1446 
1447 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1448 
1449 	zbx_vector_uint64_create(&new_group_prototype_ids);
1450 
1451 	for (i = 0; i < groups->values_num; i++)
1452 	{
1453 		group = (zbx_lld_group_t *)groups->values[i];
1454 
1455 		if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1456 			continue;
1457 
1458 		if (0 == group->groupid)
1459 			zbx_vector_uint64_append(&new_group_prototype_ids, group->group_prototypeid);
1460 		else if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE))
1461 			upd_groups_num++;
1462 	}
1463 
1464 	if (0 == new_group_prototype_ids.values_num && 0 == upd_groups_num)
1465 		goto out;
1466 
1467 	DBbegin();
1468 
1469 	if (0 != new_group_prototype_ids.values_num)
1470 	{
1471 		if (SUCCEED != DBlock_group_prototypeids(&new_group_prototype_ids))
1472 		{
1473 			/* the host group prototype was removed while processing lld rule */
1474 			DBrollback();
1475 			goto out;
1476 		}
1477 
1478 		groupid = DBget_maxid_num("hstgrp", new_group_prototype_ids.values_num);
1479 
1480 		zbx_db_insert_prepare(&db_insert, "hstgrp", "groupid", "name", "flags", NULL);
1481 
1482 		zbx_db_insert_prepare(&db_insert_gdiscovery, "group_discovery", "groupid", "parent_group_prototypeid",
1483 				"name", NULL);
1484 
1485 		zbx_vector_ptr_create(&new_groups);
1486 	}
1487 
1488 	if (0 != upd_groups_num)
1489 	{
1490 		DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1491 	}
1492 
1493 	for (i = 0; i < groups->values_num; i++)
1494 	{
1495 		group = (zbx_lld_group_t *)groups->values[i];
1496 
1497 		if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1498 			continue;
1499 
1500 		if (0 == group->groupid)
1501 		{
1502 			group->groupid = groupid++;
1503 
1504 			zbx_db_insert_add_values(&db_insert, group->groupid, group->name,
1505 					(int)ZBX_FLAG_DISCOVERY_CREATED);
1506 
1507 			if (FAIL != (j = zbx_vector_ptr_bsearch(group_prototypes, &group->group_prototypeid,
1508 					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1509 			{
1510 				group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[j];
1511 
1512 				zbx_db_insert_add_values(&db_insert_gdiscovery, group->groupid,
1513 						group->group_prototypeid, group_prototype->name);
1514 			}
1515 			else
1516 				THIS_SHOULD_NEVER_HAPPEN;
1517 
1518 			for (j = 0; j < group->hosts.values_num; j++)
1519 			{
1520 				host = (zbx_lld_host_t *)group->hosts.values[j];
1521 
1522 				/* hosts will be linked to a new host groups */
1523 				zbx_vector_uint64_append(&host->new_groupids, group->groupid);
1524 			}
1525 
1526 			zbx_vector_ptr_append(&new_groups, group);
1527 		}
1528 		else
1529 		{
1530 			if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE))
1531 			{
1532 				zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update hstgrp set ");
1533 				if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1534 				{
1535 					name_esc = DBdyn_escape_string(group->name);
1536 
1537 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "name='%s'", name_esc);
1538 
1539 					zbx_free(name_esc);
1540 				}
1541 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1542 						" where groupid=" ZBX_FS_UI64 ";\n", group->groupid);
1543 			}
1544 
1545 			if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1546 			{
1547 				if (FAIL != (j = zbx_vector_ptr_bsearch(group_prototypes, &group->group_prototypeid,
1548 						ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1549 				{
1550 					group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[j];
1551 
1552 					name_proto_esc = DBdyn_escape_string(group_prototype->name);
1553 
1554 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1555 							"update group_discovery"
1556 							" set name='%s'"
1557 							" where groupid=" ZBX_FS_UI64 ";\n",
1558 							name_proto_esc, group->groupid);
1559 
1560 					zbx_free(name_proto_esc);
1561 				}
1562 				else
1563 					THIS_SHOULD_NEVER_HAPPEN;
1564 			}
1565 		}
1566 	}
1567 
1568 	if (0 != upd_groups_num)
1569 	{
1570 		DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1571 		DBexecute("%s", sql);
1572 		zbx_free(sql);
1573 	}
1574 
1575 	if (0 != new_group_prototype_ids.values_num)
1576 	{
1577 		zbx_db_insert_execute(&db_insert);
1578 		zbx_db_insert_clean(&db_insert);
1579 
1580 		zbx_db_insert_execute(&db_insert_gdiscovery);
1581 		zbx_db_insert_clean(&db_insert_gdiscovery);
1582 
1583 		lld_groups_save_rights(&new_groups);
1584 		zbx_vector_ptr_destroy(&new_groups);
1585 	}
1586 
1587 	DBcommit();
1588 out:
1589 	zbx_vector_uint64_destroy(&new_group_prototype_ids);
1590 
1591 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1592 }
1593 
1594 /******************************************************************************
1595  *                                                                            *
1596  * Function: lld_hostmacros_get                                               *
1597  *                                                                            *
1598  * Purpose: retrieve list of host macros which should be present on the each  *
1599  *          discovered host                                                   *
1600  *                                                                            *
1601  * Parameters: hostmacros - [OUT] list of host macros                         *
1602  *                                                                            *
1603  ******************************************************************************/
lld_hostmacros_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * hostmacros)1604 static void	lld_hostmacros_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *hostmacros)
1605 {
1606 	const char		*__function_name = "lld_hostmacros_get";
1607 
1608 	DB_RESULT		result;
1609 	DB_ROW			row;
1610 	zbx_lld_hostmacro_t	*hostmacro;
1611 
1612 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1613 
1614 	result = DBselect(
1615 			"select hm.macro,hm.value"
1616 			" from hostmacro hm,items i"
1617 			" where hm.hostid=i.hostid"
1618 				" and i.itemid=" ZBX_FS_UI64,
1619 			lld_ruleid);
1620 
1621 	while (NULL != (row = DBfetch(result)))
1622 	{
1623 		hostmacro = (zbx_lld_hostmacro_t *)zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1624 
1625 		hostmacro->macro = zbx_strdup(NULL, row[0]);
1626 		hostmacro->value = zbx_strdup(NULL, row[1]);
1627 
1628 		zbx_vector_ptr_append(hostmacros, hostmacro);
1629 	}
1630 	DBfree_result(result);
1631 
1632 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1633 }
1634 
1635 /******************************************************************************
1636  *                                                                            *
1637  * Function: lld_hostmacros_make                                              *
1638  *                                                                            *
1639  * Parameters: hostmacros       - [IN] list of host macros which              *
1640  *                                     should be present on the each          *
1641  *                                     discovered host                        *
1642  *             hosts            - [IN/OUT] list of hosts                      *
1643  *                                         should be sorted by hostid         *
1644  *             del_hostmacroids - [OUT] list of host macros which should be   *
1645  *                                      deleted                               *
1646  *                                                                            *
1647  ******************************************************************************/
lld_hostmacros_make(const zbx_vector_ptr_t * hostmacros,zbx_vector_ptr_t * hosts,zbx_vector_uint64_t * del_hostmacroids)1648 static void	lld_hostmacros_make(const zbx_vector_ptr_t *hostmacros, zbx_vector_ptr_t *hosts,
1649 		zbx_vector_uint64_t *del_hostmacroids)
1650 {
1651 	const char		*__function_name = "lld_hostmacros_make";
1652 
1653 	DB_RESULT		result;
1654 	DB_ROW			row;
1655 	int			i, j;
1656 	zbx_vector_uint64_t	hostids;
1657 	zbx_uint64_t		hostmacroid, hostid;
1658 	zbx_lld_host_t		*host;
1659 	zbx_lld_hostmacro_t	*hostmacro = NULL;
1660 
1661 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1662 
1663 	zbx_vector_uint64_create(&hostids);
1664 
1665 	for (i = 0; i < hosts->values_num; i++)
1666 	{
1667 		host = (zbx_lld_host_t *)hosts->values[i];
1668 
1669 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1670 			continue;
1671 
1672 		zbx_vector_ptr_reserve(&host->new_hostmacros, hostmacros->values_num);
1673 		for (j = 0; j < hostmacros->values_num; j++)
1674 		{
1675 			hostmacro = (zbx_lld_hostmacro_t *)zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1676 
1677 			hostmacro->hostmacroid = 0;
1678 			hostmacro->macro = zbx_strdup(NULL, ((zbx_lld_hostmacro_t *)hostmacros->values[j])->macro);
1679 			hostmacro->value = zbx_strdup(NULL, ((zbx_lld_hostmacro_t *)hostmacros->values[j])->value);
1680 
1681 			zbx_vector_ptr_append(&host->new_hostmacros, hostmacro);
1682 		}
1683 
1684 		if (0 != host->hostid)
1685 			zbx_vector_uint64_append(&hostids, host->hostid);
1686 	}
1687 
1688 	if (0 != hostids.values_num)
1689 	{
1690 		char	*sql = NULL;
1691 		size_t	sql_alloc = 0, sql_offset = 0;
1692 
1693 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1694 				"select hostmacroid,hostid,macro,value"
1695 				" from hostmacro"
1696 				" where");
1697 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
1698 
1699 		result = DBselect("%s", sql);
1700 
1701 		zbx_free(sql);
1702 
1703 		while (NULL != (row = DBfetch(result)))
1704 		{
1705 			ZBX_STR2UINT64(hostid, row[1]);
1706 
1707 			if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1708 			{
1709 				THIS_SHOULD_NEVER_HAPPEN;
1710 				continue;
1711 			}
1712 
1713 			host = (zbx_lld_host_t *)hosts->values[i];
1714 
1715 			for (i = 0; i < host->new_hostmacros.values_num; i++)
1716 			{
1717 				hostmacro = (zbx_lld_hostmacro_t *)host->new_hostmacros.values[i];
1718 
1719 				if (0 == strcmp(hostmacro->macro, row[2]))
1720 					break;
1721 			}
1722 
1723 			if (i == host->new_hostmacros.values_num)
1724 			{
1725 				/* host macros which should be deleted */
1726 				ZBX_STR2UINT64(hostmacroid, row[0]);
1727 				zbx_vector_uint64_append(del_hostmacroids, hostmacroid);
1728 			}
1729 			else
1730 			{
1731 				/* host macros which are already added */
1732 				if (0 == strcmp(hostmacro->value, row[3]))	/* value doesn't changed */
1733 				{
1734 					lld_hostmacro_free(hostmacro);
1735 					zbx_vector_ptr_remove(&host->new_hostmacros, i);
1736 				}
1737 				else
1738 					ZBX_STR2UINT64(hostmacro->hostmacroid, row[0]);
1739 			}
1740 		}
1741 		DBfree_result(result);
1742 
1743 		zbx_vector_uint64_sort(del_hostmacroids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1744 	}
1745 
1746 	zbx_vector_uint64_destroy(&hostids);
1747 
1748 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1749 }
1750 
1751 /******************************************************************************
1752  *                                                                            *
1753  * Function: lld_templates_make                                               *
1754  *                                                                            *
1755  * Purpose: gets templates from a host prototype                              *
1756  *                                                                            *
1757  * Parameters: parent_hostid - [IN] host prototype identifier                 *
1758  *             hosts         - [IN/OUT] list of hosts                         *
1759  *                                      should be sorted by hostid            *
1760  *                                                                            *
1761  ******************************************************************************/
lld_templates_make(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts)1762 static void	lld_templates_make(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts)
1763 {
1764 	const char		*__function_name = "lld_templates_make";
1765 
1766 	DB_RESULT		result;
1767 	DB_ROW			row;
1768 	zbx_vector_uint64_t	templateids, hostids;
1769 	zbx_uint64_t		templateid, hostid;
1770 	zbx_lld_host_t		*host;
1771 	int			i, j;
1772 
1773 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1774 
1775 	zbx_vector_uint64_create(&templateids);
1776 	zbx_vector_uint64_create(&hostids);
1777 
1778 	/* select templates which should be linked */
1779 
1780 	result = DBselect("select templateid from hosts_templates where hostid=" ZBX_FS_UI64, parent_hostid);
1781 
1782 	while (NULL != (row = DBfetch(result)))
1783 	{
1784 		ZBX_STR2UINT64(templateid, row[0]);
1785 		zbx_vector_uint64_append(&templateids, templateid);
1786 	}
1787 	DBfree_result(result);
1788 
1789 	zbx_vector_uint64_sort(&templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1790 
1791 	/* select list of already created hosts */
1792 
1793 	for (i = 0; i < hosts->values_num; i++)
1794 	{
1795 		host = (zbx_lld_host_t *)hosts->values[i];
1796 
1797 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1798 			continue;
1799 
1800 		zbx_vector_uint64_reserve(&host->lnk_templateids, templateids.values_num);
1801 		for (j = 0; j < templateids.values_num; j++)
1802 			zbx_vector_uint64_append(&host->lnk_templateids, templateids.values[j]);
1803 
1804 		if (0 != host->hostid)
1805 			zbx_vector_uint64_append(&hostids, host->hostid);
1806 	}
1807 
1808 	if (0 != hostids.values_num)
1809 	{
1810 		char	*sql = NULL;
1811 		size_t	sql_alloc = 0, sql_offset = 0;
1812 
1813 		/* select already linked temlates */
1814 
1815 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1816 				"select hostid,templateid"
1817 				" from hosts_templates"
1818 				" where");
1819 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
1820 
1821 		result = DBselect("%s", sql);
1822 
1823 		zbx_free(sql);
1824 
1825 		while (NULL != (row = DBfetch(result)))
1826 		{
1827 			ZBX_STR2UINT64(hostid, row[0]);
1828 			ZBX_STR2UINT64(templateid, row[1]);
1829 
1830 			if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1831 			{
1832 				THIS_SHOULD_NEVER_HAPPEN;
1833 				continue;
1834 			}
1835 
1836 			host = (zbx_lld_host_t *)hosts->values[i];
1837 
1838 			if (FAIL == (i = zbx_vector_uint64_bsearch(&host->lnk_templateids, templateid,
1839 					ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
1840 			{
1841 				/* templates which should be unlinked */
1842 				zbx_vector_uint64_append(&host->del_templateids, templateid);
1843 			}
1844 			else
1845 			{
1846 				/* templates which are already linked */
1847 				zbx_vector_uint64_remove(&host->lnk_templateids, i);
1848 			}
1849 		}
1850 		DBfree_result(result);
1851 
1852 		for (i = 0; i < hosts->values_num; i++)
1853 		{
1854 			host = (zbx_lld_host_t *)hosts->values[i];
1855 
1856 			if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1857 				continue;
1858 
1859 			zbx_vector_uint64_sort(&host->del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1860 		}
1861 	}
1862 
1863 	zbx_vector_uint64_destroy(&hostids);
1864 	zbx_vector_uint64_destroy(&templateids);
1865 
1866 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1867 }
1868 
1869 /******************************************************************************
1870  *                                                                            *
1871  * Function: lld_hosts_save                                                   *
1872  *                                                                            *
1873  * Parameters: hosts            - [IN] list of hosts;                         *
1874  *                                     should be sorted by hostid             *
1875  *             status           - [IN] initial host status                    *
1876  *             del_hostgroupids - [IN] host groups which should be deleted    *
1877  *             del_hostmacroids - [IN] host macros which should be deleted    *
1878  *                                                                            *
1879  ******************************************************************************/
lld_hosts_save(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts,const char * host_proto,zbx_uint64_t proxy_hostid,char ipmi_authtype,unsigned char ipmi_privilege,const char * ipmi_username,const char * ipmi_password,unsigned char status,char inventory_mode,unsigned char tls_connect,unsigned char tls_accept,const char * tls_issuer,const char * tls_subject,const char * tls_psk_identity,const char * tls_psk,const zbx_vector_uint64_t * del_hostgroupids,const zbx_vector_uint64_t * del_hostmacroids)1880 static void	lld_hosts_save(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts, const char *host_proto,
1881 		zbx_uint64_t proxy_hostid, char ipmi_authtype, unsigned char ipmi_privilege, const char *ipmi_username,
1882 		const char *ipmi_password, unsigned char status, char inventory_mode, unsigned char tls_connect,
1883 		unsigned char tls_accept, const char *tls_issuer, const char *tls_subject, const char *tls_psk_identity,
1884 		const char *tls_psk, const zbx_vector_uint64_t *del_hostgroupids,
1885 		const zbx_vector_uint64_t *del_hostmacroids)
1886 {
1887 	const char		*__function_name = "lld_hosts_save";
1888 
1889 	int			i, j, new_hosts = 0, new_host_inventories = 0, upd_hosts = 0, new_hostgroups = 0,
1890 				new_hostmacros = 0, upd_hostmacros = 0, new_interfaces = 0, upd_interfaces = 0;
1891 	zbx_lld_host_t		*host;
1892 	zbx_lld_hostmacro_t	*hostmacro;
1893 	zbx_lld_interface_t	*interface;
1894 	zbx_vector_uint64_t	upd_host_inventory_hostids, del_host_inventory_hostids, del_interfaceids;
1895 	zbx_uint64_t		hostid = 0, hostgroupid = 0, hostmacroid = 0, interfaceid = 0;
1896 	char			*sql1 = NULL, *sql2 = NULL, *value_esc;
1897 	size_t			sql1_alloc = 0, sql1_offset = 0,
1898 				sql2_alloc = 0, sql2_offset = 0;
1899 	zbx_db_insert_t		db_insert, db_insert_hdiscovery, db_insert_hinventory, db_insert_hgroups,
1900 				db_insert_hmacro, db_insert_interface, db_insert_idiscovery;
1901 
1902 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1903 
1904 	zbx_vector_uint64_create(&upd_host_inventory_hostids);
1905 	zbx_vector_uint64_create(&del_host_inventory_hostids);
1906 	zbx_vector_uint64_create(&del_interfaceids);
1907 
1908 	for (i = 0; i < hosts->values_num; i++)
1909 	{
1910 		host = (zbx_lld_host_t *)hosts->values[i];
1911 
1912 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1913 			continue;
1914 
1915 		if (0 == host->hostid)
1916 		{
1917 			new_hosts++;
1918 			if (HOST_INVENTORY_DISABLED != inventory_mode)
1919 				new_host_inventories++;
1920 		}
1921 		else
1922 		{
1923 			if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE))
1924 				upd_hosts++;
1925 
1926 			if (host->inventory_mode != inventory_mode)
1927 			{
1928 				if (HOST_INVENTORY_DISABLED == inventory_mode)
1929 					zbx_vector_uint64_append(&del_host_inventory_hostids, host->hostid);
1930 				else if (HOST_INVENTORY_DISABLED == host->inventory_mode)
1931 					new_host_inventories++;
1932 				else
1933 					zbx_vector_uint64_append(&upd_host_inventory_hostids, host->hostid);
1934 			}
1935 		}
1936 
1937 		new_hostgroups += host->new_groupids.values_num;
1938 
1939 		for (j = 0; j < host->interfaces.values_num; j++)
1940 		{
1941 			interface = (zbx_lld_interface_t *)host->interfaces.values[j];
1942 
1943 			if (0 == interface->interfaceid)
1944 				new_interfaces++;
1945 			else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE))
1946 				upd_interfaces++;
1947 			else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
1948 				zbx_vector_uint64_append(&del_interfaceids, interface->interfaceid);
1949 		}
1950 
1951 		for (j = 0; j < host->new_hostmacros.values_num; j++)
1952 		{
1953 			hostmacro = (zbx_lld_hostmacro_t *)host->new_hostmacros.values[j];
1954 
1955 			if (0 == hostmacro->hostmacroid)
1956 				new_hostmacros++;
1957 			else
1958 				upd_hostmacros++;
1959 		}
1960 	}
1961 
1962 	if (0 == new_hosts && 0 == new_host_inventories && 0 == upd_hosts && 0 == upd_interfaces &&
1963 			0 == upd_hostmacros && 0 == new_hostgroups && 0 == new_hostmacros && 0 == new_interfaces &&
1964 			0 == del_hostgroupids->values_num && 0 == del_hostmacroids->values_num &&
1965 			0 == upd_host_inventory_hostids.values_num && 0 == del_host_inventory_hostids.values_num &&
1966 			0 == del_interfaceids.values_num)
1967 	{
1968 		goto out;
1969 	}
1970 
1971 	DBbegin();
1972 
1973 	if (SUCCEED != DBlock_hostid(parent_hostid))
1974 	{
1975 		/* the host prototype was removed while processing lld rule */
1976 		DBrollback();
1977 		goto out;
1978 	}
1979 
1980 	if (0 != new_hosts)
1981 	{
1982 		hostid = DBget_maxid_num("hosts", new_hosts);
1983 
1984 		zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "host", "name", "proxy_hostid", "ipmi_authtype",
1985 				"ipmi_privilege", "ipmi_username", "ipmi_password", "status", "flags", "tls_connect",
1986 				"tls_accept", "tls_issuer", "tls_subject", "tls_psk_identity", "tls_psk", NULL);
1987 
1988 		zbx_db_insert_prepare(&db_insert_hdiscovery, "host_discovery", "hostid", "parent_hostid", "host", NULL);
1989 	}
1990 
1991 	if (0 != new_host_inventories)
1992 	{
1993 		zbx_db_insert_prepare(&db_insert_hinventory, "host_inventory", "hostid", "inventory_mode", NULL);
1994 	}
1995 
1996 	if (0 != upd_hosts || 0 != upd_interfaces || 0 != upd_hostmacros)
1997 	{
1998 		DBbegin_multiple_update(&sql1, &sql1_alloc, &sql1_offset);
1999 	}
2000 
2001 	if (0 != new_hostgroups)
2002 	{
2003 		hostgroupid = DBget_maxid_num("hosts_groups", new_hostgroups);
2004 
2005 		zbx_db_insert_prepare(&db_insert_hgroups, "hosts_groups", "hostgroupid", "hostid", "groupid", NULL);
2006 	}
2007 
2008 	if (0 != new_hostmacros)
2009 	{
2010 		hostmacroid = DBget_maxid_num("hostmacro", new_hostmacros);
2011 
2012 		zbx_db_insert_prepare(&db_insert_hmacro, "hostmacro", "hostmacroid", "hostid", "macro", "value", NULL);
2013 	}
2014 
2015 	if (0 != new_interfaces)
2016 	{
2017 		interfaceid = DBget_maxid_num("interface", new_interfaces);
2018 
2019 		zbx_db_insert_prepare(&db_insert_interface, "interface", "interfaceid", "hostid", "type", "main",
2020 				"useip", "ip", "dns", "port", "bulk", NULL);
2021 
2022 		zbx_db_insert_prepare(&db_insert_idiscovery, "interface_discovery", "interfaceid",
2023 				"parent_interfaceid", NULL);
2024 	}
2025 
2026 	for (i = 0; i < hosts->values_num; i++)
2027 	{
2028 		host = (zbx_lld_host_t *)hosts->values[i];
2029 
2030 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2031 			continue;
2032 
2033 		if (0 == host->hostid)
2034 		{
2035 			host->hostid = hostid++;
2036 
2037 			zbx_db_insert_add_values(&db_insert, host->hostid, host->host, host->name, proxy_hostid,
2038 					(int)ipmi_authtype, (int)ipmi_privilege, ipmi_username, ipmi_password,
2039 					(int)status, (int)ZBX_FLAG_DISCOVERY_CREATED, (int)tls_connect,
2040 					(int)tls_accept, tls_issuer, tls_subject, tls_psk_identity, tls_psk);
2041 
2042 			zbx_db_insert_add_values(&db_insert_hdiscovery, host->hostid, parent_hostid, host_proto);
2043 
2044 			if (HOST_INVENTORY_DISABLED != inventory_mode)
2045 				zbx_db_insert_add_values(&db_insert_hinventory, host->hostid, (int)inventory_mode);
2046 		}
2047 		else
2048 		{
2049 			if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE))
2050 			{
2051 				const char	*d = "";
2052 
2053 				zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update hosts set ");
2054 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
2055 				{
2056 					value_esc = DBdyn_escape_string(host->host);
2057 
2058 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "host='%s'", value_esc);
2059 					d = ",";
2060 
2061 					zbx_free(value_esc);
2062 				}
2063 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
2064 				{
2065 					value_esc = DBdyn_escape_string(host->name);
2066 
2067 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2068 							"%sname='%s'", d, value_esc);
2069 					d = ",";
2070 
2071 					zbx_free(value_esc);
2072 				}
2073 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_PROXY))
2074 				{
2075 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2076 							"%sproxy_hostid=%s", d, DBsql_id_ins(proxy_hostid));
2077 					d = ",";
2078 				}
2079 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH))
2080 				{
2081 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2082 							"%sipmi_authtype=%d", d, (int)ipmi_authtype);
2083 					d = ",";
2084 				}
2085 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV))
2086 				{
2087 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2088 							"%sipmi_privilege=%d", d, (int)ipmi_privilege);
2089 					d = ",";
2090 				}
2091 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER))
2092 				{
2093 					value_esc = DBdyn_escape_string(ipmi_username);
2094 
2095 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2096 							"%sipmi_username='%s'", d, value_esc);
2097 					d = ",";
2098 
2099 					zbx_free(value_esc);
2100 				}
2101 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS))
2102 				{
2103 					value_esc = DBdyn_escape_string(ipmi_password);
2104 
2105 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2106 							"%sipmi_password='%s'", d, value_esc);
2107 					d = ",";
2108 
2109 					zbx_free(value_esc);
2110 				}
2111 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT))
2112 				{
2113 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2114 							"%stls_connect=%d", d, tls_connect);
2115 					d = ",";
2116 				}
2117 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT))
2118 				{
2119 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2120 							"%stls_accept=%d", d, tls_accept);
2121 					d = ",";
2122 				}
2123 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER))
2124 				{
2125 					value_esc = DBdyn_escape_string(tls_issuer);
2126 
2127 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2128 							"%stls_issuer='%s'", d, value_esc);
2129 					d = ",";
2130 
2131 					zbx_free(value_esc);
2132 				}
2133 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT))
2134 				{
2135 					value_esc = DBdyn_escape_string(tls_subject);
2136 
2137 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2138 							"%stls_subject='%s'", d, value_esc);
2139 					d = ",";
2140 
2141 					zbx_free(value_esc);
2142 				}
2143 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY))
2144 				{
2145 					value_esc = DBdyn_escape_string(tls_psk_identity);
2146 
2147 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2148 							"%stls_psk_identity='%s'", d, value_esc);
2149 					d = ",";
2150 
2151 					zbx_free(value_esc);
2152 				}
2153 				if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK))
2154 				{
2155 					value_esc = DBdyn_escape_string(tls_psk);
2156 
2157 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2158 							"%stls_psk='%s'", d, value_esc);
2159 
2160 					zbx_free(value_esc);
2161 				}
2162 				zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, " where hostid=" ZBX_FS_UI64 ";\n",
2163 						host->hostid);
2164 			}
2165 
2166 			if (host->inventory_mode != inventory_mode && HOST_INVENTORY_DISABLED == host->inventory_mode)
2167 				zbx_db_insert_add_values(&db_insert_hinventory, host->hostid, (int)inventory_mode);
2168 
2169 			if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
2170 			{
2171 				value_esc = DBdyn_escape_string(host_proto);
2172 
2173 				zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2174 						"update host_discovery"
2175 						" set host='%s'"
2176 						" where hostid=" ZBX_FS_UI64 ";\n",
2177 						value_esc, host->hostid);
2178 
2179 				zbx_free(value_esc);
2180 			}
2181 		}
2182 
2183 		for (j = 0; j < host->interfaces.values_num; j++)
2184 		{
2185 			interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2186 
2187 			if (0 == interface->interfaceid)
2188 			{
2189 				interface->interfaceid = interfaceid++;
2190 
2191 				zbx_db_insert_add_values(&db_insert_interface, interface->interfaceid, host->hostid,
2192 						(int)interface->type, (int)interface->main, (int)interface->useip,
2193 						interface->ip, interface->dns, interface->port, (int)interface->bulk);
2194 
2195 				zbx_db_insert_add_values(&db_insert_idiscovery, interface->interfaceid,
2196 						interface->parent_interfaceid);
2197 			}
2198 			else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE))
2199 			{
2200 				const char	*d = "";
2201 
2202 				zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update interface set ");
2203 				if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
2204 				{
2205 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "type=%d",
2206 							(int)interface->type);
2207 					d = ",";
2208 				}
2209 				if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN))
2210 				{
2211 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%smain=%d",
2212 							d, (int)interface->main);
2213 					d = ",";
2214 				}
2215 				if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP))
2216 				{
2217 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%suseip=%d",
2218 							d, (int)interface->useip);
2219 					d = ",";
2220 				}
2221 				if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_IP))
2222 				{
2223 					value_esc = DBdyn_escape_string(interface->ip);
2224 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sip='%s'", d, value_esc);
2225 					zbx_free(value_esc);
2226 					d = ",";
2227 				}
2228 				if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS))
2229 				{
2230 					value_esc = DBdyn_escape_string(interface->dns);
2231 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sdns='%s'", d, value_esc);
2232 					zbx_free(value_esc);
2233 					d = ",";
2234 				}
2235 				if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT))
2236 				{
2237 					value_esc = DBdyn_escape_string(interface->port);
2238 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sport='%s'",
2239 							d, value_esc);
2240 					zbx_free(value_esc);
2241 					d = ",";
2242 				}
2243 				if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_BULK))
2244 				{
2245 					zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sbulk=%d",
2246 							d, (int)interface->bulk);
2247 				}
2248 				zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2249 						" where interfaceid=" ZBX_FS_UI64 ";\n", interface->interfaceid);
2250 			}
2251 		}
2252 
2253 		for (j = 0; j < host->new_groupids.values_num; j++)
2254 		{
2255 			zbx_db_insert_add_values(&db_insert_hgroups, hostgroupid++, host->hostid,
2256 					host->new_groupids.values[j]);
2257 		}
2258 
2259 		for (j = 0; j < host->new_hostmacros.values_num; j++)
2260 		{
2261 			hostmacro = (zbx_lld_hostmacro_t *)host->new_hostmacros.values[j];
2262 
2263 			value_esc = DBdyn_escape_string(hostmacro->value);
2264 
2265 			if (0 == hostmacro->hostmacroid)
2266 			{
2267 				zbx_db_insert_add_values(&db_insert_hmacro, hostmacroid++, host->hostid,
2268 						hostmacro->macro, hostmacro->value);
2269 			}
2270 			else
2271 			{
2272 				zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2273 						"update hostmacro"
2274 						" set value='%s'"
2275 						" where hostmacroid=" ZBX_FS_UI64 ";\n",
2276 						value_esc, hostmacro->hostmacroid);
2277 			}
2278 
2279 			zbx_free(value_esc);
2280 		}
2281 	}
2282 
2283 	if (0 != new_hosts)
2284 	{
2285 		zbx_db_insert_execute(&db_insert);
2286 		zbx_db_insert_clean(&db_insert);
2287 
2288 		zbx_db_insert_execute(&db_insert_hdiscovery);
2289 		zbx_db_insert_clean(&db_insert_hdiscovery);
2290 	}
2291 
2292 	if (0 != new_host_inventories)
2293 	{
2294 		zbx_db_insert_execute(&db_insert_hinventory);
2295 		zbx_db_insert_clean(&db_insert_hinventory);
2296 	}
2297 
2298 	if (0 != new_hostgroups)
2299 	{
2300 		zbx_db_insert_execute(&db_insert_hgroups);
2301 		zbx_db_insert_clean(&db_insert_hgroups);
2302 	}
2303 
2304 	if (0 != new_hostmacros)
2305 	{
2306 		zbx_db_insert_execute(&db_insert_hmacro);
2307 		zbx_db_insert_clean(&db_insert_hmacro);
2308 	}
2309 
2310 	if (0 != new_interfaces)
2311 	{
2312 		zbx_db_insert_execute(&db_insert_interface);
2313 		zbx_db_insert_clean(&db_insert_interface);
2314 
2315 		zbx_db_insert_execute(&db_insert_idiscovery);
2316 		zbx_db_insert_clean(&db_insert_idiscovery);
2317 	}
2318 
2319 	if (0 != upd_hosts || 0 != upd_interfaces || 0 != upd_hostmacros)
2320 	{
2321 		DBend_multiple_update(&sql1, &sql1_alloc, &sql1_offset);
2322 		DBexecute("%s", sql1);
2323 		zbx_free(sql1);
2324 	}
2325 
2326 	if (0 != del_hostgroupids->values_num || 0 != del_hostmacroids->values_num ||
2327 			0 != upd_host_inventory_hostids.values_num || 0 != del_host_inventory_hostids.values_num ||
2328 			0 != del_interfaceids.values_num)
2329 	{
2330 		DBbegin_multiple_update(&sql2, &sql2_alloc, &sql2_offset);
2331 
2332 		if (0 != del_hostgroupids->values_num)
2333 		{
2334 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from hosts_groups where");
2335 			DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostgroupid",
2336 					del_hostgroupids->values, del_hostgroupids->values_num);
2337 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2338 		}
2339 
2340 		if (0 != del_hostmacroids->values_num)
2341 		{
2342 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from hostmacro where");
2343 			DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostmacroid",
2344 					del_hostmacroids->values, del_hostmacroids->values_num);
2345 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2346 		}
2347 
2348 		if (0 != upd_host_inventory_hostids.values_num)
2349 		{
2350 			zbx_snprintf_alloc(&sql2, &sql2_alloc, &sql2_offset,
2351 					"update host_inventory set inventory_mode=%d where", (int)inventory_mode);
2352 			DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostid",
2353 					upd_host_inventory_hostids.values, upd_host_inventory_hostids.values_num);
2354 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2355 		}
2356 
2357 		if (0 != del_host_inventory_hostids.values_num)
2358 		{
2359 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from host_inventory where");
2360 			DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostid",
2361 					del_host_inventory_hostids.values, del_host_inventory_hostids.values_num);
2362 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2363 		}
2364 
2365 		if (0 != del_interfaceids.values_num)
2366 		{
2367 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from interface where");
2368 			DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "interfaceid",
2369 					del_interfaceids.values, del_interfaceids.values_num);
2370 			zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
2371 		}
2372 
2373 		DBend_multiple_update(&sql2, &sql2_alloc, &sql2_offset);
2374 		DBexecute("%s", sql2);
2375 		zbx_free(sql2);
2376 	}
2377 
2378 	DBcommit();
2379 out:
2380 	zbx_vector_uint64_destroy(&del_interfaceids);
2381 	zbx_vector_uint64_destroy(&del_host_inventory_hostids);
2382 	zbx_vector_uint64_destroy(&upd_host_inventory_hostids);
2383 
2384 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2385 }
2386 
2387 /******************************************************************************
2388  *                                                                            *
2389  * Function: lld_templates_link                                               *
2390  *                                                                            *
2391  ******************************************************************************/
lld_templates_link(const zbx_vector_ptr_t * hosts,char ** error)2392 static void	lld_templates_link(const zbx_vector_ptr_t *hosts, char **error)
2393 {
2394 	const char	*__function_name = "lld_templates_link";
2395 
2396 	int		i;
2397 	zbx_lld_host_t	*host;
2398 	char		*err;
2399 
2400 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2401 
2402 	for (i = 0; i < hosts->values_num; i++)
2403 	{
2404 		host = (zbx_lld_host_t *)hosts->values[i];
2405 
2406 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2407 			continue;
2408 
2409 		if (0 != host->del_templateids.values_num)
2410 		{
2411 			if (SUCCEED != DBdelete_template_elements(host->hostid, &host->del_templateids, &err))
2412 			{
2413 				*error = zbx_strdcatf(*error, "Cannot unlink template: %s.\n", err);
2414 				zbx_free(err);
2415 			}
2416 		}
2417 
2418 		if (0 != host->lnk_templateids.values_num)
2419 		{
2420 			if (SUCCEED != DBcopy_template_elements(host->hostid, &host->lnk_templateids, &err))
2421 			{
2422 				*error = zbx_strdcatf(*error, "Cannot link template(s) %s.\n", err);
2423 				zbx_free(err);
2424 			}
2425 		}
2426 	}
2427 
2428 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2429 }
2430 
2431 /******************************************************************************
2432  *                                                                            *
2433  * Function: lld_hosts_remove                                                 *
2434  *                                                                            *
2435  * Purpose: updates host_discovery.lastcheck and host_discovery.ts_delete     *
2436  *          fields; removes lost resources                                    *
2437  *                                                                            *
2438  ******************************************************************************/
lld_hosts_remove(const zbx_vector_ptr_t * hosts,int lifetime,int lastcheck)2439 static void	lld_hosts_remove(const zbx_vector_ptr_t *hosts, int lifetime, int lastcheck)
2440 {
2441 	char			*sql = NULL;
2442 	size_t			sql_alloc = 0, sql_offset = 0;
2443 	const zbx_lld_host_t	*host;
2444 	zbx_vector_uint64_t	del_hostids, lc_hostids, ts_hostids;
2445 	int			i;
2446 
2447 	if (0 == hosts->values_num)
2448 		return;
2449 
2450 	zbx_vector_uint64_create(&del_hostids);
2451 	zbx_vector_uint64_create(&lc_hostids);
2452 	zbx_vector_uint64_create(&ts_hostids);
2453 
2454 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
2455 
2456 	for (i = 0; i < hosts->values_num; i++)
2457 	{
2458 		host = (zbx_lld_host_t *)hosts->values[i];
2459 
2460 		if (0 == host->hostid)
2461 			continue;
2462 
2463 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2464 		{
2465 			int	ts_delete = lld_end_of_life(host->lastcheck, lifetime);
2466 
2467 			if (lastcheck > ts_delete)
2468 			{
2469 				zbx_vector_uint64_append(&del_hostids, host->hostid);
2470 			}
2471 			else if (host->ts_delete != ts_delete)
2472 			{
2473 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2474 						"update host_discovery"
2475 						" set ts_delete=%d"
2476 						" where hostid=" ZBX_FS_UI64 ";\n",
2477 						ts_delete, host->hostid);
2478 			}
2479 		}
2480 		else
2481 		{
2482 			zbx_vector_uint64_append(&lc_hostids, host->hostid);
2483 			if (0 != host->ts_delete)
2484 				zbx_vector_uint64_append(&ts_hostids, host->hostid);
2485 		}
2486 	}
2487 
2488 	if (0 != lc_hostids.values_num)
2489 	{
2490 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update host_discovery set lastcheck=%d where",
2491 				lastcheck);
2492 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
2493 				lc_hostids.values, lc_hostids.values_num);
2494 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2495 	}
2496 
2497 	if (0 != ts_hostids.values_num)
2498 	{
2499 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update host_discovery set ts_delete=0 where");
2500 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
2501 				ts_hostids.values, ts_hostids.values_num);
2502 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2503 	}
2504 
2505 	if (16 < sql_offset)	/* in ORACLE always present begin..end; */
2506 	{
2507 		DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
2508 
2509 		DBbegin();
2510 
2511 		DBexecute("%s", sql);
2512 
2513 		DBcommit();
2514 	}
2515 
2516 	zbx_free(sql);
2517 
2518 	if (0 != del_hostids.values_num)
2519 	{
2520 		zbx_vector_uint64_sort(&del_hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2521 
2522 		DBbegin();
2523 
2524 		DBdelete_hosts(&del_hostids);
2525 
2526 		DBcommit();
2527 	}
2528 
2529 	zbx_vector_uint64_destroy(&ts_hostids);
2530 	zbx_vector_uint64_destroy(&lc_hostids);
2531 	zbx_vector_uint64_destroy(&del_hostids);
2532 }
2533 
2534 /******************************************************************************
2535  *                                                                            *
2536  * Function: lld_groups_remove                                                *
2537  *                                                                            *
2538  * Purpose: updates group_discovery.lastcheck and group_discovery.ts_delete   *
2539  *          fields; removes lost resources                                    *
2540  *                                                                            *
2541  ******************************************************************************/
lld_groups_remove(const zbx_vector_ptr_t * groups,int lifetime,int lastcheck)2542 static void	lld_groups_remove(const zbx_vector_ptr_t *groups, int lifetime, int lastcheck)
2543 {
2544 	char			*sql = NULL;
2545 	size_t			sql_alloc = 0, sql_offset = 0;
2546 	const zbx_lld_group_t	*group;
2547 	zbx_vector_uint64_t	del_groupids, lc_groupids, ts_groupids;
2548 	int			i;
2549 
2550 	if (0 == groups->values_num)
2551 		return;
2552 
2553 	zbx_vector_uint64_create(&del_groupids);
2554 	zbx_vector_uint64_create(&lc_groupids);
2555 	zbx_vector_uint64_create(&ts_groupids);
2556 
2557 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
2558 
2559 	for (i = 0; i < groups->values_num; i++)
2560 	{
2561 		group = (zbx_lld_group_t *)groups->values[i];
2562 
2563 		if (0 == group->groupid)
2564 			continue;
2565 
2566 		if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
2567 		{
2568 			int	ts_delete = lld_end_of_life(group->lastcheck, lifetime);
2569 
2570 			if (lastcheck > ts_delete)
2571 			{
2572 				zbx_vector_uint64_append(&del_groupids, group->groupid);
2573 			}
2574 			else if (group->ts_delete != ts_delete)
2575 			{
2576 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2577 						"update group_discovery"
2578 						" set ts_delete=%d"
2579 						" where groupid=" ZBX_FS_UI64 ";\n",
2580 						ts_delete, group->groupid);
2581 			}
2582 		}
2583 		else
2584 		{
2585 			zbx_vector_uint64_append(&lc_groupids, group->groupid);
2586 			if (0 != group->ts_delete)
2587 				zbx_vector_uint64_append(&ts_groupids, group->groupid);
2588 		}
2589 	}
2590 
2591 	if (0 != lc_groupids.values_num)
2592 	{
2593 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update group_discovery set lastcheck=%d where",
2594 				lastcheck);
2595 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
2596 				lc_groupids.values, lc_groupids.values_num);
2597 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2598 	}
2599 
2600 	if (0 != ts_groupids.values_num)
2601 	{
2602 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update group_discovery set ts_delete=0 where");
2603 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
2604 				ts_groupids.values, ts_groupids.values_num);
2605 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2606 	}
2607 
2608 	if (16 < sql_offset)	/* in ORACLE always present begin..end; */
2609 	{
2610 		DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
2611 
2612 		DBbegin();
2613 
2614 		DBexecute("%s", sql);
2615 
2616 		DBcommit();
2617 	}
2618 
2619 	zbx_free(sql);
2620 
2621 	if (0 != del_groupids.values_num)
2622 	{
2623 		zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2624 
2625 		DBbegin();
2626 
2627 		DBdelete_groups(&del_groupids);
2628 
2629 		DBcommit();
2630 	}
2631 
2632 	zbx_vector_uint64_destroy(&ts_groupids);
2633 	zbx_vector_uint64_destroy(&lc_groupids);
2634 	zbx_vector_uint64_destroy(&del_groupids);
2635 }
2636 
2637 /******************************************************************************
2638  *                                                                            *
2639  * Function: lld_interfaces_get                                               *
2640  *                                                                            *
2641  * Purpose: retrieves list of interfaces from the lld rule's host             *
2642  *                                                                            *
2643  ******************************************************************************/
lld_interfaces_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * interfaces)2644 static void	lld_interfaces_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *interfaces)
2645 {
2646 	DB_RESULT		result;
2647 	DB_ROW			row;
2648 	zbx_lld_interface_t	*interface;
2649 
2650 	result = DBselect(
2651 			"select hi.interfaceid,hi.type,hi.main,hi.useip,hi.ip,hi.dns,hi.port,hi.bulk"
2652 			" from interface hi,items i"
2653 			" where hi.hostid=i.hostid"
2654 				" and i.itemid=" ZBX_FS_UI64,
2655 			lld_ruleid);
2656 
2657 	while (NULL != (row = DBfetch(result)))
2658 	{
2659 		interface = (zbx_lld_interface_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
2660 
2661 		ZBX_STR2UINT64(interface->interfaceid, row[0]);
2662 		interface->type = (unsigned char)atoi(row[1]);
2663 		interface->main = (unsigned char)atoi(row[2]);
2664 		interface->useip = (unsigned char)atoi(row[3]);
2665 		interface->ip = zbx_strdup(NULL, row[4]);
2666 		interface->dns = zbx_strdup(NULL, row[5]);
2667 		interface->port = zbx_strdup(NULL, row[6]);
2668 		interface->bulk = (unsigned char)atoi(row[7]);
2669 
2670 		zbx_vector_ptr_append(interfaces, interface);
2671 	}
2672 	DBfree_result(result);
2673 
2674 	zbx_vector_ptr_sort(interfaces, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2675 }
2676 
2677 /******************************************************************************
2678  *                                                                            *
2679  * Function: lld_interface_make                                               *
2680  *                                                                            *
2681  ******************************************************************************/
lld_interface_make(zbx_vector_ptr_t * interfaces,zbx_uint64_t parent_interfaceid,zbx_uint64_t interfaceid,unsigned char type,unsigned char main,unsigned char useip,const char * ip,const char * dns,const char * port,unsigned char bulk)2682 static void	lld_interface_make(zbx_vector_ptr_t *interfaces, zbx_uint64_t parent_interfaceid,
2683 		zbx_uint64_t interfaceid, unsigned char type, unsigned char main, unsigned char useip, const char *ip,
2684 		const char *dns, const char *port, unsigned char bulk)
2685 {
2686 	zbx_lld_interface_t	*interface = NULL;
2687 	int			i;
2688 
2689 	for (i = 0; i < interfaces->values_num; i++)
2690 	{
2691 		interface = (zbx_lld_interface_t *)interfaces->values[i];
2692 
2693 		if (0 != interface->interfaceid)
2694 			continue;
2695 
2696 		if (interface->parent_interfaceid == parent_interfaceid)
2697 			break;
2698 	}
2699 
2700 	if (i == interfaces->values_num)
2701 	{
2702 		/* interface which should be deleted */
2703 		interface = (zbx_lld_interface_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
2704 
2705 		interface->interfaceid = interfaceid;
2706 		interface->parent_interfaceid = 0;
2707 		interface->type = type;
2708 		interface->main = main;
2709 		interface->useip = 0;
2710 		interface->ip = NULL;
2711 		interface->dns = NULL;
2712 		interface->port = NULL;
2713 		interface->bulk = SNMP_BULK_ENABLED;
2714 		interface->flags = ZBX_FLAG_LLD_INTERFACE_REMOVE;
2715 
2716 		zbx_vector_ptr_append(interfaces, interface);
2717 	}
2718 	else
2719 	{
2720 		/* interface which are already added */
2721 		if (interface->type != type)
2722 		{
2723 			interface->type_orig = type;
2724 			interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE;
2725 		}
2726 		if (interface->main != main)
2727 		{
2728 			interface->main_orig = main;
2729 			interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
2730 		}
2731 		if (interface->useip != useip)
2732 			interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP;
2733 		if (0 != strcmp(interface->ip, ip))
2734 			interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_IP;
2735 		if (0 != strcmp(interface->dns, dns))
2736 			interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS;
2737 		if (0 != strcmp(interface->port, port))
2738 			interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT;
2739 		if (interface->bulk != bulk)
2740 			interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_BULK;
2741 	}
2742 
2743 	interface->interfaceid = interfaceid;
2744 }
2745 
2746 /******************************************************************************
2747  *                                                                            *
2748  * Function: lld_interfaces_make                                              *
2749  *                                                                            *
2750  * Parameters: interfaces - [IN] sorted list of interfaces which              *
2751  *                               should be present on the each                *
2752  *                               discovered host                              *
2753  *             hosts      - [IN/OUT] sorted list of hosts                     *
2754  *                                                                            *
2755  ******************************************************************************/
lld_interfaces_make(const zbx_vector_ptr_t * interfaces,zbx_vector_ptr_t * hosts)2756 static void	lld_interfaces_make(const zbx_vector_ptr_t *interfaces, zbx_vector_ptr_t *hosts)
2757 {
2758 	const char		*__function_name = "lld_interfaces_make";
2759 
2760 	DB_RESULT		result;
2761 	DB_ROW			row;
2762 	int			i, j;
2763 	zbx_vector_uint64_t	hostids;
2764 	zbx_uint64_t		parent_interfaceid, hostid, interfaceid;
2765 	zbx_lld_host_t		*host;
2766 	zbx_lld_interface_t	*new_interface, *interface;
2767 
2768 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2769 
2770 	zbx_vector_uint64_create(&hostids);
2771 
2772 	for (i = 0; i < hosts->values_num; i++)
2773 	{
2774 		host = (zbx_lld_host_t *)hosts->values[i];
2775 
2776 		if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2777 			continue;
2778 
2779 		zbx_vector_ptr_reserve(&host->interfaces, interfaces->values_num);
2780 		for (j = 0; j < interfaces->values_num; j++)
2781 		{
2782 			interface = (zbx_lld_interface_t *)interfaces->values[j];
2783 
2784 			new_interface = (zbx_lld_interface_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
2785 
2786 			new_interface->interfaceid = 0;
2787 			new_interface->parent_interfaceid = interface->interfaceid;
2788 			new_interface->type = interface->type;
2789 			new_interface->main = interface->main;
2790 			new_interface->useip = interface->useip;
2791 			new_interface->ip = zbx_strdup(NULL, interface->ip);
2792 			new_interface->dns = zbx_strdup(NULL, interface->dns);
2793 			new_interface->port = zbx_strdup(NULL, interface->port);
2794 			new_interface->bulk = interface->bulk;
2795 			new_interface->flags = 0x00;
2796 
2797 			zbx_vector_ptr_append(&host->interfaces, new_interface);
2798 		}
2799 
2800 		if (0 != host->hostid)
2801 			zbx_vector_uint64_append(&hostids, host->hostid);
2802 	}
2803 
2804 	if (0 != hostids.values_num)
2805 	{
2806 		char	*sql = NULL;
2807 		size_t	sql_alloc = 0, sql_offset = 0;
2808 
2809 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
2810 				"select hi.hostid,id.parent_interfaceid,hi.interfaceid,hi.type,hi.main,hi.useip,hi.ip,"
2811 					"hi.dns,hi.port,hi.bulk"
2812 				" from interface hi"
2813 					" left join interface_discovery id"
2814 						" on hi.interfaceid=id.interfaceid"
2815 				" where");
2816 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hi.hostid", hostids.values, hostids.values_num);
2817 
2818 		result = DBselect("%s", sql);
2819 
2820 		zbx_free(sql);
2821 
2822 		while (NULL != (row = DBfetch(result)))
2823 		{
2824 			ZBX_STR2UINT64(hostid, row[0]);
2825 			ZBX_DBROW2UINT64(parent_interfaceid, row[1]);
2826 			ZBX_DBROW2UINT64(interfaceid, row[2]);
2827 
2828 			if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2829 			{
2830 				THIS_SHOULD_NEVER_HAPPEN;
2831 				continue;
2832 			}
2833 
2834 			host = (zbx_lld_host_t *)hosts->values[i];
2835 
2836 			lld_interface_make(&host->interfaces, parent_interfaceid, interfaceid,
2837 					(unsigned char)atoi(row[3]), (unsigned char)atoi(row[4]),
2838 					(unsigned char)atoi(row[5]), row[6], row[7], row[8],
2839 					(unsigned char)atoi(row[9]));
2840 		}
2841 		DBfree_result(result);
2842 	}
2843 
2844 	zbx_vector_uint64_destroy(&hostids);
2845 
2846 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2847 }
2848 
2849 /******************************************************************************
2850  *                                                                            *
2851  * Function: another_main_interface_exists                                    *
2852  *                                                                            *
2853  * Return value: SUCCEED if interface with same type exists in the list of    *
2854  *               interfaces; FAIL - otherwise                                 *
2855  *                                                                            *
2856  * Comments: interfaces with ZBX_FLAG_LLD_INTERFACE_REMOVE flag are ignored   *
2857  *           auxiliary function for lld_interfaces_validate()                 *
2858  *                                                                            *
2859  ******************************************************************************/
another_main_interface_exists(const zbx_vector_ptr_t * interfaces,const zbx_lld_interface_t * interface)2860 static int	another_main_interface_exists(const zbx_vector_ptr_t *interfaces, const zbx_lld_interface_t *interface)
2861 {
2862 	const zbx_lld_interface_t	*interface_b;
2863 	int				i;
2864 
2865 	for (i = 0; i < interfaces->values_num; i++)
2866 	{
2867 		interface_b = (zbx_lld_interface_t *)interfaces->values[i];
2868 
2869 		if (interface_b == interface)
2870 			continue;
2871 
2872 		if (0 != (interface_b->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
2873 			continue;
2874 
2875 		if (interface_b->type != interface->type)
2876 			continue;
2877 
2878 		if (1 == interface_b->main)
2879 			return SUCCEED;
2880 	}
2881 
2882 	return FAIL;
2883 }
2884 
2885 /******************************************************************************
2886  *                                                                            *
2887  * Function: lld_interfaces_validate                                          *
2888  *                                                                            *
2889  * Parameters: hosts - [IN/OUT] list of hosts                                 *
2890  *                                                                            *
2891  ******************************************************************************/
lld_interfaces_validate(zbx_vector_ptr_t * hosts,char ** error)2892 static void	lld_interfaces_validate(zbx_vector_ptr_t *hosts, char **error)
2893 {
2894 	const char		*__function_name = "lld_interfaces_validate";
2895 
2896 	DB_RESULT		result;
2897 	DB_ROW			row;
2898 	int			i, j;
2899 	zbx_vector_uint64_t	interfaceids;
2900 	zbx_uint64_t		interfaceid;
2901 	zbx_lld_host_t		*host;
2902 	zbx_lld_interface_t	*interface;
2903 	unsigned char		type;
2904 	char			*sql = NULL;
2905 	size_t			sql_alloc = 0, sql_offset = 0;
2906 
2907 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2908 
2909 	/* validate changed types */
2910 
2911 	zbx_vector_uint64_create(&interfaceids);
2912 
2913 	for (i = 0; i < hosts->values_num; i++)
2914 	{
2915 		host = (zbx_lld_host_t *)hosts->values[i];
2916 
2917 		for (j = 0; j < host->interfaces.values_num; j++)
2918 		{
2919 			interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2920 
2921 			if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
2922 				continue;
2923 
2924 			zbx_vector_uint64_append(&interfaceids, interface->interfaceid);
2925 		}
2926 	}
2927 
2928 	if (0 != interfaceids.values_num)
2929 	{
2930 		zbx_vector_uint64_sort(&interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2931 
2932 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select interfaceid,type from items where");
2933 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "interfaceid",
2934 				interfaceids.values, interfaceids.values_num);
2935 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " group by interfaceid,type");
2936 
2937 		result = DBselect("%s", sql);
2938 
2939 		while (NULL != (row = DBfetch(result)))
2940 		{
2941 			type = get_interface_type_by_item_type((unsigned char)atoi(row[1]));
2942 
2943 			if (type != INTERFACE_TYPE_ANY && type != INTERFACE_TYPE_UNKNOWN)
2944 			{
2945 				ZBX_STR2UINT64(interfaceid, row[0]);
2946 
2947 				for (i = 0; i < hosts->values_num; i++)
2948 				{
2949 					host = (zbx_lld_host_t *)hosts->values[i];
2950 
2951 					for (j = 0; j < host->interfaces.values_num; j++)
2952 					{
2953 						interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2954 
2955 						if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
2956 							continue;
2957 
2958 						if (interface->interfaceid != interfaceid)
2959 							continue;
2960 
2961 						*error = zbx_strdcatf(*error,
2962 								"Cannot update \"%s\" interface on host \"%s\":"
2963 								" the interface is used by items.\n",
2964 								zbx_interface_type_string(interface->type_orig),
2965 								host->host);
2966 
2967 						/* return an original interface type and drop the correspond flag */
2968 						interface->type = interface->type_orig;
2969 						interface->flags &= ~ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE;
2970 					}
2971 				}
2972 			}
2973 		}
2974 		DBfree_result(result);
2975 	}
2976 
2977 	/* validate interfaces which should be deleted */
2978 
2979 	zbx_vector_uint64_clear(&interfaceids);
2980 
2981 	for (i = 0; i < hosts->values_num; i++)
2982 	{
2983 		host = (zbx_lld_host_t *)hosts->values[i];
2984 
2985 		for (j = 0; j < host->interfaces.values_num; j++)
2986 		{
2987 			interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2988 
2989 			if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
2990 				continue;
2991 
2992 			zbx_vector_uint64_append(&interfaceids, interface->interfaceid);
2993 		}
2994 	}
2995 
2996 	if (0 != interfaceids.values_num)
2997 	{
2998 		zbx_vector_uint64_sort(&interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2999 
3000 		sql_offset = 0;
3001 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select interfaceid from items where");
3002 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "interfaceid",
3003 				interfaceids.values, interfaceids.values_num);
3004 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " group by interfaceid");
3005 
3006 		result = DBselect("%s", sql);
3007 
3008 		while (NULL != (row = DBfetch(result)))
3009 		{
3010 			ZBX_STR2UINT64(interfaceid, row[0]);
3011 
3012 			for (i = 0; i < hosts->values_num; i++)
3013 			{
3014 				host = (zbx_lld_host_t *)hosts->values[i];
3015 
3016 				for (j = 0; j < host->interfaces.values_num; j++)
3017 				{
3018 					interface = (zbx_lld_interface_t *)host->interfaces.values[j];
3019 
3020 					if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
3021 						continue;
3022 
3023 					if (interface->interfaceid != interfaceid)
3024 						continue;
3025 
3026 					*error = zbx_strdcatf(*error, "Cannot delete \"%s\" interface on host \"%s\":"
3027 							" the interface is used by items.\n",
3028 							zbx_interface_type_string(interface->type), host->host);
3029 
3030 					/* drop the correspond flag */
3031 					interface->flags &= ~ZBX_FLAG_LLD_INTERFACE_REMOVE;
3032 
3033 					if (SUCCEED == another_main_interface_exists(&host->interfaces, interface))
3034 					{
3035 						if (1 == interface->main)
3036 						{
3037 							/* drop main flag */
3038 							interface->main_orig = interface->main;
3039 							interface->main = 0;
3040 							interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
3041 						}
3042 					}
3043 					else if (1 != interface->main)
3044 					{
3045 						/* set main flag */
3046 						interface->main_orig = interface->main;
3047 						interface->main = 1;
3048 						interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
3049 					}
3050 				}
3051 			}
3052 		}
3053 		DBfree_result(result);
3054 	}
3055 
3056 	zbx_vector_uint64_destroy(&interfaceids);
3057 
3058 	zbx_free(sql);
3059 
3060 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3061 }
3062 
3063 /******************************************************************************
3064  *                                                                            *
3065  * Function: lld_update_hosts                                                 *
3066  *                                                                            *
3067  * Purpose: add or update low-level discovered hosts                          *
3068  *                                                                            *
3069  ******************************************************************************/
lld_update_hosts(zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * lld_rows,char ** error,int lifetime,int lastcheck)3070 void	lld_update_hosts(zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *lld_rows, char **error, int lifetime,
3071 		int lastcheck)
3072 {
3073 	const char		*__function_name = "lld_update_hosts";
3074 
3075 	DB_RESULT		result;
3076 	DB_ROW			row;
3077 	zbx_vector_ptr_t	hosts, group_prototypes, groups, interfaces, hostmacros;
3078 	zbx_vector_uint64_t	groupids;		/* list of host groups which should be added */
3079 	zbx_vector_uint64_t	del_hostgroupids;	/* list of host groups which should be deleted */
3080 	zbx_vector_uint64_t	del_hostmacroids;	/* list of host macros which should be deleted */
3081 	zbx_uint64_t		proxy_hostid;
3082 	char			*ipmi_username = NULL, *ipmi_password, *tls_issuer, *tls_subject, *tls_psk_identity,
3083 				*tls_psk;
3084 	char			ipmi_authtype, inventory_mode;
3085 	unsigned char		ipmi_privilege, tls_connect, tls_accept;
3086 
3087 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3088 
3089 	result = DBselect(
3090 			"select h.proxy_hostid,h.ipmi_authtype,h.ipmi_privilege,h.ipmi_username,h.ipmi_password,"
3091 				"h.tls_connect,h.tls_accept,h.tls_issuer,h.tls_subject,h.tls_psk_identity,h.tls_psk"
3092 			" from hosts h,items i"
3093 			" where h.hostid=i.hostid"
3094 				" and i.itemid=" ZBX_FS_UI64,
3095 			lld_ruleid);
3096 
3097 	if (NULL != (row = DBfetch(result)))
3098 	{
3099 		ZBX_DBROW2UINT64(proxy_hostid, row[0]);
3100 		ipmi_authtype = (char)atoi(row[1]);
3101 		ZBX_STR2UCHAR(ipmi_privilege, row[2]);
3102 		ipmi_username = zbx_strdup(NULL, row[3]);
3103 		ipmi_password = zbx_strdup(NULL, row[4]);
3104 
3105 		ZBX_STR2UCHAR(tls_connect, row[5]);
3106 		ZBX_STR2UCHAR(tls_accept, row[6]);
3107 		tls_issuer = zbx_strdup(NULL, row[7]);
3108 		tls_subject = zbx_strdup(NULL, row[8]);
3109 		tls_psk_identity = zbx_strdup(NULL, row[9]);
3110 		tls_psk = zbx_strdup(NULL, row[10]);
3111 	}
3112 	DBfree_result(result);
3113 
3114 	if (NULL == row)
3115 	{
3116 		*error = zbx_strdcatf(*error, "Cannot process host prototypes: a parent host not found.\n");
3117 		return;
3118 	}
3119 
3120 	zbx_vector_ptr_create(&hosts);
3121 	zbx_vector_uint64_create(&groupids);
3122 	zbx_vector_ptr_create(&group_prototypes);
3123 	zbx_vector_ptr_create(&groups);
3124 	zbx_vector_uint64_create(&del_hostgroupids);
3125 	zbx_vector_uint64_create(&del_hostmacroids);
3126 	zbx_vector_ptr_create(&interfaces);
3127 	zbx_vector_ptr_create(&hostmacros);
3128 
3129 	lld_interfaces_get(lld_ruleid, &interfaces);
3130 	lld_hostmacros_get(lld_ruleid, &hostmacros);
3131 
3132 	result = DBselect(
3133 			"select h.hostid,h.host,h.name,h.status,hi.inventory_mode"
3134 			" from hosts h,host_discovery hd"
3135 				" left join host_inventory hi"
3136 					" on hd.hostid=hi.hostid"
3137 			" where h.hostid=hd.hostid"
3138 				" and hd.parent_itemid=" ZBX_FS_UI64,
3139 			lld_ruleid);
3140 
3141 	while (NULL != (row = DBfetch(result)))
3142 	{
3143 		zbx_uint64_t	parent_hostid;
3144 		const char	*host_proto, *name_proto;
3145 		zbx_lld_host_t	*host;
3146 		unsigned char	status;
3147 		int		i;
3148 
3149 		ZBX_STR2UINT64(parent_hostid, row[0]);
3150 		host_proto = row[1];
3151 		name_proto = row[2];
3152 		status = (unsigned char)atoi(row[3]);
3153 		if (SUCCEED == DBis_null(row[4]))
3154 			inventory_mode = HOST_INVENTORY_DISABLED;
3155 		else
3156 			inventory_mode = (char)atoi(row[4]);
3157 
3158 		lld_hosts_get(parent_hostid, &hosts, proxy_hostid, ipmi_authtype, ipmi_privilege, ipmi_username,
3159 				ipmi_password, tls_connect, tls_accept, tls_issuer, tls_subject,
3160 				tls_psk_identity, tls_psk);
3161 
3162 		lld_simple_groups_get(parent_hostid, &groupids);
3163 
3164 		lld_group_prototypes_get(parent_hostid, &group_prototypes);
3165 		lld_groups_get(parent_hostid, &groups);
3166 
3167 		for (i = 0; i < lld_rows->values_num; i++)
3168 		{
3169 			const zbx_lld_row_t	*lld_row = (zbx_lld_row_t *)lld_rows->values[i];
3170 
3171 			host = lld_host_make(&hosts, host_proto, name_proto, &lld_row->jp_row);
3172 			lld_groups_make(host, &groups, &group_prototypes, &lld_row->jp_row);
3173 		}
3174 
3175 		zbx_vector_ptr_sort(&hosts, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3176 
3177 		lld_groups_validate(&groups, error);
3178 		lld_hosts_validate(&hosts, error);
3179 
3180 		lld_interfaces_make(&interfaces, &hosts);
3181 		lld_interfaces_validate(&hosts, error);
3182 
3183 		lld_hostgroups_make(&groupids, &hosts, &groups, &del_hostgroupids);
3184 		lld_templates_make(parent_hostid, &hosts);
3185 		lld_hostmacros_make(&hostmacros, &hosts, &del_hostmacroids);
3186 
3187 		lld_groups_save(&groups, &group_prototypes);
3188 		lld_hosts_save(parent_hostid, &hosts, host_proto, proxy_hostid, ipmi_authtype, ipmi_privilege,
3189 				ipmi_username, ipmi_password, status, inventory_mode, tls_connect, tls_accept,
3190 				tls_issuer, tls_subject, tls_psk_identity, tls_psk, &del_hostgroupids,
3191 				&del_hostmacroids);
3192 
3193 		/* linking of the templates */
3194 		lld_templates_link(&hosts, error);
3195 
3196 		lld_hosts_remove(&hosts, lifetime, lastcheck);
3197 		lld_groups_remove(&groups, lifetime, lastcheck);
3198 
3199 		zbx_vector_ptr_clear_ext(&groups, (zbx_clean_func_t)lld_group_free);
3200 		zbx_vector_ptr_clear_ext(&group_prototypes, (zbx_clean_func_t)lld_group_prototype_free);
3201 		zbx_vector_ptr_clear_ext(&hosts, (zbx_clean_func_t)lld_host_free);
3202 
3203 		zbx_vector_uint64_clear(&groupids);
3204 		zbx_vector_uint64_clear(&del_hostgroupids);
3205 		zbx_vector_uint64_clear(&del_hostmacroids);
3206 	}
3207 	DBfree_result(result);
3208 
3209 	zbx_vector_ptr_clear_ext(&hostmacros, (zbx_clean_func_t)lld_hostmacro_free);
3210 	zbx_vector_ptr_clear_ext(&interfaces, (zbx_clean_func_t)lld_interface_free);
3211 
3212 	zbx_vector_ptr_destroy(&hostmacros);
3213 	zbx_vector_ptr_destroy(&interfaces);
3214 	zbx_vector_uint64_destroy(&del_hostmacroids);
3215 	zbx_vector_uint64_destroy(&del_hostgroupids);
3216 	zbx_vector_ptr_destroy(&groups);
3217 	zbx_vector_ptr_destroy(&group_prototypes);
3218 	zbx_vector_uint64_destroy(&groupids);
3219 	zbx_vector_ptr_destroy(&hosts);
3220 
3221 	zbx_free(tls_psk);
3222 	zbx_free(tls_psk_identity);
3223 	zbx_free(tls_subject);
3224 	zbx_free(tls_issuer);
3225 	zbx_free(ipmi_password);
3226 	zbx_free(ipmi_username);
3227 
3228 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3229 }
3230