1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "common.h"
21 
22 #include "db.h"
23 #include "log.h"
24 #include "dbcache.h"
25 #include "zbxserver.h"
26 
27 typedef struct
28 {
29 	zbx_uint64_t	itemid;
30 	zbx_uint64_t	valuemapid;
31 	zbx_uint64_t	interfaceid;
32 	zbx_uint64_t	templateid;
33 	char		*name;
34 	char		*key;
35 	char		*delay_flex;
36 	char		*trapper_hosts;
37 	char		*units;
38 	char		*formula;
39 	char		*logtimefmt;
40 	char		*params;
41 	char		*ipmi_sensor;
42 	char		*snmp_community;
43 	char		*snmp_oid;
44 	char		*snmpv3_securityname;
45 	char		*snmpv3_authpassphrase;
46 	char		*snmpv3_privpassphrase;
47 	char		*snmpv3_contextname;
48 	char		*username;
49 	char		*password;
50 	char		*publickey;
51 	char		*privatekey;
52 	char		*description;
53 	char		*lifetime;
54 	char		*port;
55 	int		delay;
56 	int		history;
57 	int		trends;
58 	unsigned char	type;
59 	unsigned char	value_type;
60 	unsigned char	data_type;
61 	unsigned char	status;
62 	unsigned char	multiplier;
63 	unsigned char	delta;
64 	unsigned char	snmpv3_securitylevel;
65 	unsigned char	snmpv3_authprotocol;
66 	unsigned char	snmpv3_privprotocol;
67 	unsigned char	authtype;
68 	unsigned char	flags;
69 	unsigned char	inventory_link;
70 	unsigned char	evaltype;
71 }
72 zbx_template_item_t;
73 
74 /* lld rule condition */
75 typedef struct
76 {
77 	zbx_uint64_t	item_conditionid;
78 	char		*macro;
79 	char		*value;
80 	unsigned char	operator;
81 }
82 zbx_lld_rule_condition_t;
83 
84 /* lld rule */
85 typedef struct
86 {
87 	/* discovery rule source id */
88 	zbx_uint64_t		templateid;
89 	/* discovery rule source conditions */
90 	zbx_vector_ptr_t	conditions;
91 
92 	/* discovery rule destination id */
93 	zbx_uint64_t		itemid;
94 	/* the starting id to be used for destination condition ids */
95 	zbx_uint64_t		conditionid;
96 	/* discovery rule destination condition ids */
97 	zbx_vector_uint64_t	conditionids;
98 }
99 zbx_lld_rule_map_t;
100 
101 /* auxiliary function for DBcopy_template_items() */
DBget_interfaces_by_hostid(zbx_uint64_t hostid,zbx_uint64_t * interfaceids)102 static void	DBget_interfaces_by_hostid(zbx_uint64_t hostid, zbx_uint64_t *interfaceids)
103 {
104 	DB_RESULT	result;
105 	DB_ROW		row;
106 	unsigned char	type;
107 
108 	result = DBselect(
109 			"select type,interfaceid"
110 			" from interface"
111 			" where hostid=" ZBX_FS_UI64
112 				" and type in (%d,%d,%d,%d)"
113 				" and main=1",
114 			hostid, INTERFACE_TYPE_AGENT, INTERFACE_TYPE_SNMP, INTERFACE_TYPE_IPMI, INTERFACE_TYPE_JMX);
115 
116 	while (NULL != (row = DBfetch(result)))
117 	{
118 		ZBX_STR2UCHAR(type, row[0]);
119 		ZBX_STR2UINT64(interfaceids[type - 1], row[1]);
120 	}
121 	DBfree_result(result);
122 }
123 
124 /******************************************************************************
125  *                                                                            *
126  * Function: get_template_items                                               *
127  *                                                                            *
128  * Purpose: read template items from database                                 *
129  *                                                                            *
130  * Parameters: hostid      - [IN] host id                                     *
131  *             templateids - [IN] array of template IDs                       *
132  *             items       - [OUT] the item data                              *
133  *                                                                            *
134  * Comments: The itemid and key are set depending on whether the item exists  *
135  *           for the specified host.                                          *
136  *           If item exists itemid will be set to its itemid and key will be  *
137  *           set to NULL.                                                     *
138  *           If item does not exist, itemid will be set to 0 and key will be  *
139  *           set to item key.                                                 *
140  *                                                                            *
141  ******************************************************************************/
get_template_items(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids,zbx_vector_ptr_t * items)142 static void	get_template_items(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids, zbx_vector_ptr_t *items)
143 {
144 	DB_RESULT		result;
145 	DB_ROW			row;
146 	char			*sql = NULL;
147 	size_t			sql_alloc = 0, sql_offset = 0, i;
148 	unsigned char		interface_type;
149 	zbx_template_item_t	*item;
150 	zbx_uint64_t		interfaceids[4];
151 
152 	memset(&interfaceids, 0, sizeof(interfaceids));
153 	DBget_interfaces_by_hostid(hostid, interfaceids);
154 
155 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
156 			"select ti.itemid,ti.name,ti.key_,ti.type,ti.value_type,ti.data_type,ti.delay,ti.delay_flex,"
157 				"ti.history,ti.trends,ti.status,ti.trapper_hosts,ti.units,ti.multiplier,ti.delta,"
158 				"ti.formula,ti.logtimefmt,ti.valuemapid,ti.params,ti.ipmi_sensor,ti.snmp_community,"
159 				"ti.snmp_oid,ti.snmpv3_securityname,ti.snmpv3_securitylevel,ti.snmpv3_authprotocol,"
160 				"ti.snmpv3_authpassphrase,ti.snmpv3_privprotocol,ti.snmpv3_privpassphrase,ti.authtype,"
161 				"ti.username,ti.password,ti.publickey,ti.privatekey,ti.flags,ti.description,"
162 				"ti.inventory_link,ti.lifetime,ti.snmpv3_contextname,hi.itemid,ti.evaltype,ti.port"
163 			" from items ti"
164 			" left join items hi on hi.key_=ti.key_"
165 				" and hi.hostid=" ZBX_FS_UI64
166 			" where",
167 			hostid);
168 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num);
169 
170 	result = DBselect("%s", sql);
171 
172 	while (NULL != (row = DBfetch(result)))
173 	{
174 		item = zbx_malloc(NULL, sizeof(zbx_template_item_t));
175 
176 		ZBX_STR2UINT64(item->templateid, row[0]);
177 		ZBX_STR2UCHAR(item->type, row[3]);
178 		ZBX_STR2UCHAR(item->value_type, row[4]);
179 		ZBX_STR2UCHAR(item->data_type, row[5]);
180 		item->delay = atoi(row[6]);
181 		item->history = atoi(row[8]);
182 		item->trends = atoi(row[9]);
183 		ZBX_STR2UCHAR(item->status, row[10]);
184 		ZBX_STR2UCHAR(item->multiplier, row[13]);
185 		ZBX_STR2UCHAR(item->delta, row[14]);
186 		ZBX_DBROW2UINT64(item->valuemapid, row[17]);
187 		ZBX_STR2UCHAR(item->snmpv3_securitylevel, row[23]);
188 		ZBX_STR2UCHAR(item->snmpv3_authprotocol, row[24]);
189 		ZBX_STR2UCHAR(item->snmpv3_privprotocol, row[26]);
190 		ZBX_STR2UCHAR(item->authtype, row[28]);
191 		ZBX_STR2UCHAR(item->flags, row[33]);
192 		ZBX_STR2UCHAR(item->inventory_link, row[35]);
193 		ZBX_STR2UCHAR(item->evaltype, row[39]);
194 
195 		switch (interface_type = get_interface_type_by_item_type(item->type))
196 		{
197 			case INTERFACE_TYPE_UNKNOWN:
198 				item->interfaceid = 0;
199 				break;
200 			case INTERFACE_TYPE_ANY:
201 				for (i = 0; INTERFACE_TYPE_COUNT > i; i++)
202 				{
203 					if (0 != interfaceids[INTERFACE_TYPE_PRIORITY[i] - 1])
204 						break;
205 				}
206 				item->interfaceid = interfaceids[INTERFACE_TYPE_PRIORITY[i] - 1];
207 				break;
208 			default:
209 				item->interfaceid = interfaceids[interface_type - 1];
210 		}
211 
212 		item->name = zbx_strdup(NULL, row[1]);
213 		item->delay_flex = zbx_strdup(NULL, row[7]);
214 		item->trapper_hosts = zbx_strdup(NULL, row[11]);
215 		item->units = zbx_strdup(NULL, row[12]);
216 		item->formula = zbx_strdup(NULL, row[15]);
217 		item->logtimefmt = zbx_strdup(NULL, row[16]);
218 		item->params = zbx_strdup(NULL, row[18]);
219 		item->ipmi_sensor = zbx_strdup(NULL, row[19]);
220 		item->snmp_community = zbx_strdup(NULL, row[20]);
221 		item->snmp_oid = zbx_strdup(NULL, row[21]);
222 		item->snmpv3_securityname = zbx_strdup(NULL, row[22]);
223 		item->snmpv3_authpassphrase = zbx_strdup(NULL, row[25]);
224 		item->snmpv3_privpassphrase = zbx_strdup(NULL, row[27]);
225 		item->username = zbx_strdup(NULL, row[29]);
226 		item->password = zbx_strdup(NULL, row[30]);
227 		item->publickey = zbx_strdup(NULL, row[31]);
228 		item->privatekey = zbx_strdup(NULL, row[32]);
229 		item->description = zbx_strdup(NULL, row[34]);
230 		item->lifetime = zbx_strdup(NULL, row[36]);
231 		item->snmpv3_contextname = zbx_strdup(NULL, row[37]);
232 		item->port = zbx_strdup(NULL, row[40]);
233 
234 		if (SUCCEED != DBis_null(row[38]))
235 		{
236 			item->key = NULL;
237 			ZBX_STR2UINT64(item->itemid, row[38]);
238 		}
239 		else
240 		{
241 			item->key = zbx_strdup(NULL, row[2]);
242 			item->itemid = 0;
243 		}
244 
245 		zbx_vector_ptr_append(items, item);
246 	}
247 	DBfree_result(result);
248 
249 	zbx_free(sql);
250 
251 	zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
252 }
253 
254 /******************************************************************************
255  *                                                                            *
256  * Function: get_template_lld_rule_map                                        *
257  *                                                                            *
258  * Purpose: reads template lld rule conditions and host lld_rule identifiers  *
259  *          from database                                                     *
260  *                                                                            *
261  * Parameters: items - [IN] the host items including lld rules                *
262  *             rules - [OUT] the ldd rule mapping                             *
263  *                                                                            *
264  ******************************************************************************/
get_template_lld_rule_map(const zbx_vector_ptr_t * items,zbx_vector_ptr_t * rules)265 static void	get_template_lld_rule_map(const zbx_vector_ptr_t *items, zbx_vector_ptr_t *rules)
266 {
267 	zbx_template_item_t		*item;
268 	zbx_lld_rule_map_t		*rule;
269 	zbx_lld_rule_condition_t	*condition;
270 	int				i, index;
271 	zbx_vector_uint64_t		itemids;
272 	DB_RESULT			result;
273 	DB_ROW				row;
274 	char				*sql = NULL;
275 	size_t				sql_alloc = 0, sql_offset = 0;
276 	zbx_uint64_t			itemid, item_conditionid;
277 
278 	zbx_vector_uint64_create(&itemids);
279 
280 	/* prepare discovery rules */
281 	for (i = 0; i < items->values_num; i++)
282 	{
283 		item = items->values[i];
284 
285 		if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags))
286 			continue;
287 
288 		rule = zbx_malloc(NULL, sizeof(zbx_lld_rule_map_t));
289 
290 		rule->itemid = item->itemid;
291 		rule->templateid = item->templateid;
292 		rule->conditionid = 0;
293 		zbx_vector_uint64_create(&rule->conditionids);
294 		zbx_vector_ptr_create(&rule->conditions);
295 
296 		zbx_vector_ptr_append(rules, rule);
297 
298 		if (0 != rule->itemid)
299 			zbx_vector_uint64_append(&itemids, rule->itemid);
300 		zbx_vector_uint64_append(&itemids, rule->templateid);
301 	}
302 
303 	if (0 != itemids.values_num)
304 	{
305 		zbx_vector_ptr_sort(rules, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
306 		zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
307 
308 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
309 				"select item_conditionid,itemid,operator,macro,value from item_condition where");
310 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids.values, itemids.values_num);
311 
312 		result = DBselect("%s", sql);
313 
314 		while (NULL != (row = DBfetch(result)))
315 		{
316 			ZBX_STR2UINT64(itemid, row[1]);
317 
318 			index = zbx_vector_ptr_bsearch(rules, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
319 
320 			if (FAIL != index)
321 			{
322 				/* read template lld conditions */
323 
324 				rule = (zbx_lld_rule_map_t *)rules->values[index];
325 
326 				condition = zbx_malloc(NULL, sizeof(zbx_lld_rule_condition_t));
327 
328 				ZBX_STR2UINT64(condition->item_conditionid, row[0]);
329 				ZBX_STR2UCHAR(condition->operator, row[2]);
330 				condition->macro = zbx_strdup(NULL, row[3]);
331 				condition->value = zbx_strdup(NULL, row[4]);
332 
333 				zbx_vector_ptr_append(&rule->conditions, condition);
334 			}
335 			else
336 			{
337 				/* read host lld conditions identifiers */
338 
339 				for (i = 0; i < rules->values_num; i++)
340 				{
341 					rule = (zbx_lld_rule_map_t *)rules->values[i];
342 
343 					if (itemid != rule->itemid)
344 						continue;
345 
346 					ZBX_STR2UINT64(item_conditionid, row[0]);
347 					zbx_vector_uint64_append(&rule->conditionids, item_conditionid);
348 
349 					break;
350 				}
351 
352 				if (i == rules->values_num)
353 					THIS_SHOULD_NEVER_HAPPEN;
354 			}
355 		}
356 		DBfree_result(result);
357 
358 		zbx_free(sql);
359 	}
360 
361 	zbx_vector_uint64_destroy(&itemids);
362 }
363 
364 /******************************************************************************
365  *                                                                            *
366  * Function: calculate_template_lld_rule_conditionids                         *
367  *                                                                            *
368  * Purpose: calculate identifiers for new item conditions                     *
369  *                                                                            *
370  * Parameters: rules - [IN] the ldd rule mapping                              *
371  *                                                                            *
372  * Return value: The number of new item conditions to be inserted.            *
373  *                                                                            *
374  ******************************************************************************/
calculate_template_lld_rule_conditionids(zbx_vector_ptr_t * rules)375 static int	calculate_template_lld_rule_conditionids(zbx_vector_ptr_t *rules)
376 {
377 	zbx_lld_rule_map_t	*rule;
378 	int			i, conditions_num = 0;
379 	zbx_uint64_t		conditionid;
380 
381 	/* calculate the number of new conditions to be inserted */
382 	for (i = 0; i < rules->values_num; i++)
383 	{
384 		rule = rules->values[i];
385 
386 		if (rule->conditions.values_num > rule->conditionids.values_num)
387 			conditions_num += rule->conditions.values_num - rule->conditionids.values_num;
388 	}
389 
390 	/* reserve ids for the new conditions to be inserted and assign to lld rules */
391 	if (0 == conditions_num)
392 		goto out;
393 
394 	conditionid = DBget_maxid_num("item_condition", conditions_num);
395 
396 	for (i = 0; i < rules->values_num; i++)
397 	{
398 		rule = rules->values[i];
399 
400 		if (rule->conditions.values_num <= rule->conditionids.values_num)
401 			continue;
402 
403 		rule->conditionid = conditionid;
404 		conditionid += rule->conditions.values_num - rule->conditionids.values_num;
405 	}
406 out:
407 	return conditions_num;
408 }
409 
410 /******************************************************************************
411  *                                                                            *
412  * Function: update_template_lld_rule_formulas                                *
413  *                                                                            *
414  * Purpose: translate template item condition identifiers in expression type  *
415  *          discovery rule formulas to refer the host item condition          *
416  *          identifiers instead.                                              *
417  *                                                                            *
418  * Parameters:  items  - [IN] the template items                              *
419  *              rules  - [IN] the ldd rule mapping                            *
420  *                                                                            *
421  ******************************************************************************/
update_template_lld_rule_formulas(zbx_vector_ptr_t * items,zbx_vector_ptr_t * rules)422 static void	update_template_lld_rule_formulas(zbx_vector_ptr_t *items, zbx_vector_ptr_t *rules)
423 {
424 	zbx_lld_rule_map_t	*rule;
425 	int			i, j, index;
426 	char			*formula;
427 	zbx_uint64_t		conditionid;
428 
429 	for (i = 0; i < items->values_num; i++)
430 	{
431 		zbx_template_item_t	*item = items->values[i];
432 
433 		if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags) || CONDITION_EVAL_TYPE_EXPRESSION != item->evaltype)
434 			continue;
435 
436 		index = zbx_vector_ptr_bsearch(rules, &item->templateid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
437 
438 		if (FAIL == index)
439 		{
440 			THIS_SHOULD_NEVER_HAPPEN;
441 			continue;
442 		}
443 
444 		rule = rules->values[index];
445 
446 		formula = zbx_strdup(NULL, item->formula);
447 
448 		conditionid = rule->conditionid;
449 
450 		for (j = 0; j < rule->conditions.values_num; j++)
451 		{
452 			zbx_uint64_t			id;
453 			char				srcid[64], dstid[64], *ptr;
454 			size_t				pos = 0, len;
455 
456 			zbx_lld_rule_condition_t	*condition = rule->conditions.values[j];
457 
458 			if (j < rule->conditionids.values_num)
459 				id = rule->conditionids.values[j];
460 			else
461 				id = conditionid++;
462 
463 			zbx_snprintf(srcid, sizeof(srcid), "{" ZBX_FS_UI64 "}", condition->item_conditionid);
464 			zbx_snprintf(dstid, sizeof(dstid), "{" ZBX_FS_UI64 "}", id);
465 
466 			len = strlen(srcid);
467 
468 			while (NULL != (ptr = strstr(formula + pos, srcid)))
469 			{
470 				pos = ptr - formula + len - 1;
471 				zbx_replace_string(&formula, ptr - formula, &pos, dstid);
472 			}
473 		}
474 
475 		zbx_free(item->formula);
476 		item->formula = formula;
477 	}
478 }
479 
480 /******************************************************************************
481  *                                                                            *
482  * Function: save_template_items                                              *
483  *                                                                            *
484  * Purpose: saves template items to the target host in database               *
485  *                                                                            *
486  * Parameters:  hostid - [IN] the target host                                 *
487  *              items  - [IN] the template items                              *
488  *              rules  - [IN] the ldd rule mapping                            *
489  *                                                                            *
490  ******************************************************************************/
save_template_items(zbx_uint64_t hostid,zbx_vector_ptr_t * items)491 void	save_template_items(zbx_uint64_t hostid, zbx_vector_ptr_t *items)
492 {
493 	char		*sql = NULL;
494 	size_t		sql_alloc = 16 * ZBX_KIBIBYTE, sql_offset = 0;
495 	int		new_items = items->values_num, i;
496 	zbx_uint64_t	itemid;
497 	zbx_db_insert_t	db_insert;
498 
499 	sql = zbx_malloc(sql, sql_alloc);
500 
501 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
502 
503 	for (i = 0; i < items->values_num; i++)
504 	{
505 		char			*name_esc, *delay_flex_esc, *trapper_hosts_esc, *units_esc, *formula_esc,
506 					*logtimefmt_esc, *params_esc, *ipmi_sensor_esc, *snmp_community_esc,
507 					*snmp_oid_esc, *snmpv3_securityname_esc, *snmpv3_authpassphrase_esc,
508 					*snmpv3_privpassphrase_esc, *username_esc, *password_esc, *publickey_esc,
509 					*privatekey_esc, *description_esc, *lifetime_esc, *snmpv3_contextname_esc,
510 					*port_esc;
511 		zbx_template_item_t	*item = items->values[i];
512 
513 		/* skip new items */
514 		if (NULL != item->key)
515 			continue;
516 
517 		name_esc = DBdyn_escape_string(item->name);
518 		delay_flex_esc = DBdyn_escape_string(item->delay_flex);
519 		trapper_hosts_esc = DBdyn_escape_string(item->trapper_hosts);
520 		units_esc = DBdyn_escape_string(item->units);
521 		formula_esc = DBdyn_escape_string(item->formula);
522 		logtimefmt_esc = DBdyn_escape_string(item->logtimefmt);
523 		params_esc = DBdyn_escape_string(item->params);
524 		ipmi_sensor_esc = DBdyn_escape_string(item->ipmi_sensor);
525 		snmp_community_esc = DBdyn_escape_string(item->snmp_community);
526 		snmp_oid_esc = DBdyn_escape_string(item->snmp_oid);
527 		snmpv3_securityname_esc = DBdyn_escape_string(item->snmpv3_securityname);
528 		snmpv3_authpassphrase_esc = DBdyn_escape_string(item->snmpv3_authpassphrase);
529 		snmpv3_privpassphrase_esc = DBdyn_escape_string(item->snmpv3_privpassphrase);
530 		username_esc = DBdyn_escape_string(item->username);
531 		password_esc = DBdyn_escape_string(item->password);
532 		publickey_esc = DBdyn_escape_string(item->publickey);
533 		privatekey_esc = DBdyn_escape_string(item->privatekey);
534 		description_esc = DBdyn_escape_string(item->description);
535 		lifetime_esc = DBdyn_escape_string(item->lifetime);
536 		snmpv3_contextname_esc = DBdyn_escape_string(item->snmpv3_contextname);
537 		port_esc = DBdyn_escape_string(item->port);
538 
539 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
540 				"update items"
541 				" set name='%s',"
542 					"type=%d,"
543 					"value_type=%d,"
544 					"data_type=%d,"
545 					"delay=%d,"
546 					"delay_flex='%s',"
547 					"history=%d,"
548 					"trends=%d,"
549 					"status=%d,"
550 					"trapper_hosts='%s',"
551 					"units='%s',"
552 					"multiplier=%d,"
553 					"delta=%d,"
554 					"formula='%s',"
555 					"logtimefmt='%s',"
556 					"valuemapid=%s,"
557 					"params='%s',"
558 					"ipmi_sensor='%s',"
559 					"snmp_community='%s',"
560 					"snmp_oid='%s',"
561 					"snmpv3_securityname='%s',"
562 					"snmpv3_securitylevel=%d,"
563 					"snmpv3_authprotocol=%d,"
564 					"snmpv3_authpassphrase='%s',"
565 					"snmpv3_privprotocol=%d,"
566 					"snmpv3_privpassphrase='%s',"
567 					"snmpv3_contextname='%s',"
568 					"authtype=%d,"
569 					"username='%s',"
570 					"password='%s',"
571 					"publickey='%s',"
572 					"privatekey='%s',"
573 					"templateid=" ZBX_FS_UI64 ","
574 					"flags=%d,"
575 					"description='%s',"
576 					"inventory_link=%d,"
577 					"interfaceid=%s,"
578 					"lifetime='%s',"
579 					"evaltype=%d,"
580 					"port='%s'"
581 				" where itemid=" ZBX_FS_UI64 ";\n",
582 				name_esc, (int)item->type, (int)item->value_type,
583 				(int)item->data_type, item->delay, delay_flex_esc,
584 				item->history, item->trends, (int)item->status, trapper_hosts_esc,
585 				units_esc, (int)item->multiplier, (int)item->delta, formula_esc,
586 				logtimefmt_esc, DBsql_id_ins(item->valuemapid), params_esc,
587 				ipmi_sensor_esc, snmp_community_esc, snmp_oid_esc,
588 				snmpv3_securityname_esc, (int)item->snmpv3_securitylevel,
589 				(int)item->snmpv3_authprotocol, snmpv3_authpassphrase_esc,
590 				(int)item->snmpv3_privprotocol, snmpv3_privpassphrase_esc,
591 				snmpv3_contextname_esc, (int)item->authtype, username_esc,
592 				password_esc, publickey_esc, privatekey_esc,
593 				item->templateid, (int)item->flags, description_esc,
594 				(int)item->inventory_link, DBsql_id_ins(item->interfaceid),
595 				lifetime_esc, (int)item->evaltype, port_esc, item->itemid);
596 
597 		new_items--;
598 
599 		zbx_free(port_esc);
600 		zbx_free(snmpv3_contextname_esc);
601 		zbx_free(lifetime_esc);
602 		zbx_free(description_esc);
603 		zbx_free(privatekey_esc);
604 		zbx_free(publickey_esc);
605 		zbx_free(password_esc);
606 		zbx_free(username_esc);
607 		zbx_free(snmpv3_privpassphrase_esc);
608 		zbx_free(snmpv3_authpassphrase_esc);
609 		zbx_free(snmpv3_securityname_esc);
610 		zbx_free(snmp_oid_esc);
611 		zbx_free(snmp_community_esc);
612 		zbx_free(ipmi_sensor_esc);
613 		zbx_free(params_esc);
614 		zbx_free(logtimefmt_esc);
615 		zbx_free(formula_esc);
616 		zbx_free(units_esc);
617 		zbx_free(trapper_hosts_esc);
618 		zbx_free(delay_flex_esc);
619 		zbx_free(name_esc);
620 	}
621 
622 	DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
623 
624 	if (16 < sql_offset)
625 		DBexecute("%s", sql);
626 
627 	zbx_free(sql);
628 
629 	if (0 == new_items)
630 		return;
631 
632 	itemid = DBget_maxid_num("items", new_items);
633 
634 	zbx_db_insert_prepare(&db_insert, "items", "itemid", "name", "key_", "hostid", "type", "value_type",
635 			"data_type", "delay", "delay_flex", "history", "trends", "status", "trapper_hosts", "units",
636 			"multiplier", "delta", "formula", "logtimefmt", "valuemapid", "params", "ipmi_sensor",
637 			"snmp_community", "snmp_oid", "snmpv3_securityname", "snmpv3_securitylevel",
638 			"snmpv3_authprotocol", "snmpv3_authpassphrase", "snmpv3_privprotocol", "snmpv3_privpassphrase",
639 			"authtype", "username", "password", "publickey", "privatekey", "templateid", "flags",
640 			"description", "inventory_link", "interfaceid", "lifetime", "snmpv3_contextname", "evaltype",
641 			"port", NULL);
642 
643 	for (i = 0; i < items->values_num; i++)
644 	{
645 		zbx_template_item_t	*item = items->values[i];
646 
647 		/* skip existing items */
648 		if (NULL == item->key)
649 			continue;
650 
651 		zbx_db_insert_add_values(&db_insert, itemid, item->name, item->key, hostid, (int)item->type,
652 				(int)item->value_type, (int)item->data_type, item->delay, item->delay_flex,
653 				item->history, item->trends, (int)item->status, item->trapper_hosts, item->units,
654 				(int)item->multiplier, (int)item->delta, item->formula, item->logtimefmt,
655 				item->valuemapid, item->params, item->ipmi_sensor, item->snmp_community, item->snmp_oid,
656 				item->snmpv3_securityname, (int)item->snmpv3_securitylevel,
657 				(int)item->snmpv3_authprotocol, item->snmpv3_authpassphrase,
658 				(int)item->snmpv3_privprotocol, item->snmpv3_privpassphrase, (int)item->authtype,
659 				item->username, item->password, item->publickey, item->privatekey, item->templateid,
660 				(int)item->flags, item->description, (int)item->inventory_link, item->interfaceid,
661 				item->lifetime, item->snmpv3_contextname, (int)item->evaltype, item->port);
662 
663 		item->itemid = itemid++;
664 	}
665 
666 	zbx_db_insert_execute(&db_insert);
667 	zbx_db_insert_clean(&db_insert);
668 }
669 
670 /******************************************************************************
671  *                                                                            *
672  * Function: save_template_lld_rules                                          *
673  *                                                                            *
674  * Purpose: saves template lld rule item conditions to the target host in     *
675  *          database                                                          *
676  *                                                                            *
677  * Parameters:  items          - [IN] the template items                      *
678  *              rules          - [IN] the ldd rule mapping                    *
679  *              new_conditions - [IN] the number of new item conditions to    *
680  *                                    be inserted                             *
681  *                                                                            *
682  ******************************************************************************/
save_template_lld_rules(zbx_vector_ptr_t * items,zbx_vector_ptr_t * rules,int new_conditions)683 static void	save_template_lld_rules(zbx_vector_ptr_t *items, zbx_vector_ptr_t *rules, int new_conditions)
684 {
685 	char				*macro_esc, *value_esc;
686 	int				i, j, index;
687 	zbx_db_insert_t			db_insert;
688 	zbx_lld_rule_map_t		*rule;
689 	zbx_lld_rule_condition_t	*condition;
690 	char				*sql = NULL;
691 	size_t				sql_alloc = 0, sql_offset = 0;
692 	zbx_vector_uint64_t		item_conditionids;
693 
694 	if (0 == rules->values_num)
695 		return;
696 
697 	zbx_vector_uint64_create(&item_conditionids);
698 
699 	if (0 != new_conditions)
700 	{
701 		zbx_db_insert_prepare(&db_insert, "item_condition", "item_conditionid", "itemid", "operator", "macro",
702 				"value", NULL);
703 
704 		/* insert lld rule conditions for new items */
705 		for (i = 0; i < items->values_num; i++)
706 		{
707 			zbx_template_item_t	*item = items->values[i];
708 
709 			if (NULL == item->key)
710 				continue;
711 
712 			if (0 == (ZBX_FLAG_DISCOVERY_RULE & item->flags))
713 				continue;
714 
715 			index = zbx_vector_ptr_bsearch(rules, &item->templateid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
716 
717 			if (FAIL == index)
718 			{
719 				THIS_SHOULD_NEVER_HAPPEN;
720 				continue;
721 			}
722 
723 			rule = rules->values[index];
724 
725 			for (j = 0; j < rule->conditions.values_num; j++)
726 			{
727 				condition = rule->conditions.values[j];
728 
729 				zbx_db_insert_add_values(&db_insert, rule->conditionid++, item->itemid,
730 						(int)condition->operator, condition->macro, condition->value);
731 			}
732 		}
733 	}
734 
735 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
736 
737 	/* update lld rule conditions for existing items */
738 	for (i = 0; i < rules->values_num; i++)
739 	{
740 		rule = rules->values[i];
741 
742 		/* skip lld rules of new items */
743 		if (0 == rule->itemid)
744 			continue;
745 
746 		index = MIN(rule->conditions.values_num, rule->conditionids.values_num);
747 
748 		/* update intersecting rule conditions */
749 		for (j = 0; j < index; j++)
750 		{
751 			condition = rule->conditions.values[j];
752 
753 			macro_esc = DBdyn_escape_string(condition->macro);
754 			value_esc = DBdyn_escape_string(condition->value);
755 
756 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update item_condition"
757 					" set operator=%d,macro='%s',value='%s'"
758 					" where item_conditionid=" ZBX_FS_UI64 ";\n",
759 					(int)condition->operator, macro_esc, value_esc, rule->conditionids.values[j]);
760 
761 			DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
762 
763 			zbx_free(value_esc);
764 			zbx_free(macro_esc);
765 		}
766 
767 		/* delete removed rule conditions */
768 		for (j = index; j < rule->conditionids.values_num; j++)
769 			zbx_vector_uint64_append(&item_conditionids, rule->conditionids.values[j]);
770 
771 		/* insert new rule conditions */
772 		for (j = index; j < rule->conditions.values_num; j++)
773 		{
774 			condition = rule->conditions.values[j];
775 
776 			zbx_db_insert_add_values(&db_insert, rule->conditionid++, rule->itemid,
777 					(int)condition->operator, condition->macro, condition->value);
778 		}
779 	}
780 
781 	/* delete removed item conditions */
782 	if (0 != item_conditionids.values_num)
783 	{
784 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from item_condition where");
785 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "item_conditionid", item_conditionids.values,
786 				item_conditionids.values_num);
787 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
788 	}
789 
790 	DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
791 
792 	if (16 < sql_offset)
793 		DBexecute("%s", sql);
794 
795 	if (0 != new_conditions)
796 	{
797 		zbx_db_insert_execute(&db_insert);
798 		zbx_db_insert_clean(&db_insert);
799 	}
800 
801 	zbx_free(sql);
802 	zbx_vector_uint64_destroy(&item_conditionids);
803 }
804 
805 /******************************************************************************
806  *                                                                            *
807  * Function: save_template_item_applications                                  *
808  *                                                                            *
809  * Purpose: saves new item applications links in database                     *
810  *                                                                            *
811  * Parameters:  items   - [IN] the template items                             *
812  *                                                                            *
813  ******************************************************************************/
save_template_item_applications(zbx_vector_ptr_t * items)814 void	save_template_item_applications(zbx_vector_ptr_t *items)
815 {
816 	typedef struct
817 	{
818 		zbx_uint64_t	itemid;
819 		zbx_uint64_t	applicationid;
820 	}
821 	zbx_itemapp_t;
822 
823 	DB_RESULT		result;
824 	DB_ROW			row;
825 	char			*sql = NULL;
826 	size_t			sql_alloc = 0, sql_offset = 0;
827 	zbx_vector_uint64_t	itemids;
828 	zbx_vector_ptr_t	itemapps;
829 	zbx_itemapp_t		*itemapp;
830 	int 			i;
831 	zbx_db_insert_t		db_insert;
832 
833 	zbx_vector_ptr_create(&itemapps);
834 	zbx_vector_uint64_create(&itemids);
835 
836 	for (i = 0; i < items->values_num; i++)
837 	{
838 		zbx_template_item_t	*item = items->values[i];
839 
840 		zbx_vector_uint64_append(&itemids, item->itemid);
841 	}
842 
843 	zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
844 
845 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
846 			"select hi.itemid,ha.applicationid"
847 			" from items_applications tia"
848 				" join items hi on hi.templateid=tia.itemid"
849 					" and");
850 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hi.itemid", itemids.values, itemids.values_num);
851 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
852 				" join application_template hat on hat.templateid=tia.applicationid"
853 				" join applications ha on ha.applicationid=hat.applicationid"
854 					" and ha.hostid=hi.hostid"
855 					" left join items_applications hia on hia.applicationid=ha.applicationid"
856 						" and hia.itemid=hi.itemid"
857 			" where hia.itemappid is null");
858 
859 	result = DBselect("%s", sql);
860 
861 	while (NULL != (row = DBfetch(result)))
862 	{
863 		itemapp = zbx_malloc(NULL, sizeof(zbx_itemapp_t));
864 
865 		ZBX_STR2UINT64(itemapp->itemid, row[0]);
866 		ZBX_STR2UINT64(itemapp->applicationid, row[1]);
867 
868 		zbx_vector_ptr_append(&itemapps, itemapp);
869 	}
870 	DBfree_result(result);
871 
872 	if (0 == itemapps.values_num)
873 		goto out;
874 
875 	zbx_db_insert_prepare(&db_insert, "items_applications", "itemappid", "itemid", "applicationid", NULL);
876 
877 	for (i = 0; i < itemapps.values_num; i++)
878 	{
879 		itemapp = itemapps.values[i];
880 
881 		zbx_db_insert_add_values(&db_insert, __UINT64_C(0), itemapp->itemid, itemapp->applicationid);
882 	}
883 
884 	zbx_db_insert_autoincrement(&db_insert, "itemappid");
885 	zbx_db_insert_execute(&db_insert);
886 	zbx_db_insert_clean(&db_insert);
887 out:
888 	zbx_free(sql);
889 
890 	zbx_vector_uint64_destroy(&itemids);
891 
892 	zbx_vector_ptr_clear_ext(&itemapps, zbx_ptr_free);
893 	zbx_vector_ptr_destroy(&itemapps);
894 }
895 
896 /******************************************************************************
897  *                                                                            *
898  * Function: save_template_discovery_prototypes                               *
899  *                                                                            *
900  * Purpose: saves host item prototypes in database                            *
901  *                                                                            *
902  * Parameters:  hostid  - [IN] the target host                                *
903  *              items   - [IN] the template items                             *
904  *                                                                            *
905  ******************************************************************************/
save_template_discovery_prototypes(zbx_uint64_t hostid,zbx_vector_ptr_t * items)906 void	save_template_discovery_prototypes(zbx_uint64_t hostid, zbx_vector_ptr_t *items)
907 {
908 	typedef struct
909 	{
910 		zbx_uint64_t	itemid;
911 		zbx_uint64_t	parent_itemid;
912 	}
913 	zbx_proto_t;
914 
915 	DB_RESULT		result;
916 	DB_ROW			row;
917 	char			*sql = NULL;
918 	size_t			sql_alloc = 0, sql_offset = 0;
919 	zbx_vector_uint64_t	itemids;
920 	zbx_vector_ptr_t	prototypes;
921 	zbx_proto_t		*proto;
922 	int 			i;
923 	zbx_db_insert_t		db_insert;
924 
925 	zbx_vector_ptr_create(&prototypes);
926 	zbx_vector_uint64_create(&itemids);
927 
928 	for (i = 0; i < items->values_num; i++)
929 	{
930 		zbx_template_item_t	*item = items->values[i];
931 
932 		/* process only new prototype items */
933 		if (NULL == item->key || 0 == (ZBX_FLAG_DISCOVERY_PROTOTYPE & item->flags))
934 			continue;
935 
936 		zbx_vector_uint64_append(&itemids, item->itemid);
937 	}
938 
939 	if (0 == itemids.values_num)
940 		goto out;
941 
942 	zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
943 
944 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
945 			"select i.itemid,r.itemid"
946 			" from items i,item_discovery id,items r"
947 			" where i.templateid=id.itemid"
948 				" and id.parent_itemid=r.templateid"
949 				" and r.hostid=" ZBX_FS_UI64
950 				" and",
951 			hostid);
952 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid", itemids.values, itemids.values_num);
953 
954 	result = DBselect("%s", sql);
955 
956 	while (NULL != (row = DBfetch(result)))
957 	{
958 		proto = zbx_malloc(NULL, sizeof(zbx_proto_t));
959 
960 		ZBX_STR2UINT64(proto->itemid, row[0]);
961 		ZBX_STR2UINT64(proto->parent_itemid, row[1]);
962 
963 		zbx_vector_ptr_append(&prototypes, proto);
964 	}
965 	DBfree_result(result);
966 
967 	if (0 == prototypes.values_num)
968 		goto out;
969 
970 	zbx_db_insert_prepare(&db_insert, "item_discovery", "itemdiscoveryid", "itemid",
971 					"parent_itemid", NULL);
972 
973 	for (i = 0; i < prototypes.values_num; i++)
974 	{
975 		proto = prototypes.values[i];
976 
977 		zbx_db_insert_add_values(&db_insert, __UINT64_C(0), proto->itemid, proto->parent_itemid);
978 	}
979 
980 	zbx_db_insert_autoincrement(&db_insert, "itemdiscoveryid");
981 	zbx_db_insert_execute(&db_insert);
982 	zbx_db_insert_clean(&db_insert);
983 out:
984 	zbx_free(sql);
985 
986 	zbx_vector_uint64_destroy(&itemids);
987 
988 	zbx_vector_ptr_clear_ext(&prototypes, zbx_ptr_free);
989 	zbx_vector_ptr_destroy(&prototypes);
990 }
991 
992 /******************************************************************************
993  *                                                                            *
994  * Function: free_template_item                                               *
995  *                                                                            *
996  * Purpose: frees template item                                               *
997  *                                                                            *
998  * Parameters:  item  - [IN] the template item                                *
999  *                                                                            *
1000  ******************************************************************************/
free_template_item(zbx_template_item_t * item)1001 void	free_template_item(zbx_template_item_t *item)
1002 {
1003 	zbx_free(item->port);
1004 	zbx_free(item->snmpv3_contextname);
1005 	zbx_free(item->lifetime);
1006 	zbx_free(item->description);
1007 	zbx_free(item->privatekey);
1008 	zbx_free(item->publickey);
1009 	zbx_free(item->password);
1010 	zbx_free(item->username);
1011 	zbx_free(item->snmpv3_privpassphrase);
1012 	zbx_free(item->snmpv3_authpassphrase);
1013 	zbx_free(item->snmpv3_securityname);
1014 	zbx_free(item->snmp_oid);
1015 	zbx_free(item->snmp_community);
1016 	zbx_free(item->ipmi_sensor);
1017 	zbx_free(item->params);
1018 	zbx_free(item->logtimefmt);
1019 	zbx_free(item->formula);
1020 	zbx_free(item->units);
1021 	zbx_free(item->trapper_hosts);
1022 	zbx_free(item->delay_flex);
1023 	zbx_free(item->name);
1024 	zbx_free(item->key);
1025 
1026 	zbx_free(item);
1027 }
1028 
1029 /******************************************************************************
1030  *                                                                            *
1031  * Function: free_lld_rule_condition                                          *
1032  *                                                                            *
1033  * Purpose: frees lld rule condition                                          *
1034  *                                                                            *
1035  * Parameters:  item  - [IN] the lld rule condition                           *
1036  *                                                                            *
1037  ******************************************************************************/
free_lld_rule_condition(zbx_lld_rule_condition_t * condition)1038 void	free_lld_rule_condition(zbx_lld_rule_condition_t *condition)
1039 {
1040 	zbx_free(condition->macro);
1041 	zbx_free(condition->value);
1042 	zbx_free(condition);
1043 }
1044 
1045 /******************************************************************************
1046  *                                                                            *
1047  * Function: free_lld_rule_map                                                *
1048  *                                                                            *
1049  * Purpose: frees lld rule mapping                                            *
1050  *                                                                            *
1051  * Parameters:  item  - [IN] the lld rule mapping                             *
1052  *                                                                            *
1053  ******************************************************************************/
free_lld_rule_map(zbx_lld_rule_map_t * rule)1054 void	free_lld_rule_map(zbx_lld_rule_map_t *rule)
1055 {
1056 	zbx_vector_ptr_clear_ext(&rule->conditions, (zbx_clean_func_t)free_lld_rule_condition);
1057 	zbx_vector_ptr_destroy(&rule->conditions);
1058 
1059 	zbx_vector_uint64_destroy(&rule->conditionids);
1060 
1061 	zbx_free(rule);
1062 }
1063 
1064 /******************************************************************************
1065  *                                                                            *
1066  * Function: DBcopy_template_items                                            *
1067  *                                                                            *
1068  * Purpose: copy template items to host                                       *
1069  *                                                                            *
1070  * Parameters: hostid      - [IN] host id                                     *
1071  *             templateids - [IN] array of template IDs                       *
1072  *                                                                            *
1073  ******************************************************************************/
DBcopy_template_items(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)1074 void	DBcopy_template_items(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
1075 {
1076 	const char		*__function_name = "DBcopy_template_items";
1077 
1078 	zbx_vector_ptr_t	items, lld_rules;
1079 	int			new_conditions = 0;
1080 
1081 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1082 
1083 	zbx_vector_ptr_create(&items);
1084 	zbx_vector_ptr_create(&lld_rules);
1085 
1086 	get_template_items(hostid, templateids, &items);
1087 
1088 	if (0 == items.values_num)
1089 		goto out;
1090 
1091 	get_template_lld_rule_map(&items, &lld_rules);
1092 
1093 	new_conditions = calculate_template_lld_rule_conditionids(&lld_rules);
1094 	update_template_lld_rule_formulas(&items, &lld_rules);
1095 
1096 	save_template_items(hostid, &items);
1097 	save_template_lld_rules(&items, &lld_rules, new_conditions);
1098 	save_template_item_applications(&items);
1099 	save_template_discovery_prototypes(hostid, &items);
1100 out:
1101 	zbx_vector_ptr_clear_ext(&lld_rules, (zbx_clean_func_t)free_lld_rule_map);
1102 	zbx_vector_ptr_destroy(&lld_rules);
1103 
1104 	zbx_vector_ptr_clear_ext(&items, (zbx_clean_func_t)free_template_item);
1105 	zbx_vector_ptr_destroy(&items);
1106 
1107 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1108 }
1109