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 #include "zbxregexp.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		master_itemid;
33 	char			*name;
34 	char			*key;
35 	char			*delay;
36 	char			*history;
37 	char			*trends;
38 	char			*trapper_hosts;
39 	char			*units;
40 	char			*formula;
41 	char			*logtimefmt;
42 	char			*params;
43 	char			*ipmi_sensor;
44 	char			*snmp_community;
45 	char			*snmp_oid;
46 	char			*snmpv3_securityname;
47 	char			*snmpv3_authpassphrase;
48 	char			*snmpv3_privpassphrase;
49 	char			*snmpv3_contextname;
50 	char			*username;
51 	char			*password;
52 	char			*publickey;
53 	char			*privatekey;
54 	char			*description;
55 	char			*port;
56 	char			*jmx_endpoint;
57 	char			*timeout;
58 	char			*url;
59 	char			*query_fields;
60 	char			*posts;
61 	char			*status_codes;
62 	char			*http_proxy;
63 	char			*headers;
64 	char			*ssl_cert_file;
65 	char			*ssl_key_file;
66 	char			*ssl_key_password;
67 	unsigned char		verify_peer;
68 	unsigned char		verify_host;
69 	unsigned char		follow_redirects;
70 	unsigned char		post_type;
71 	unsigned char		retrieve_mode;
72 	unsigned char		request_method;
73 	unsigned char		output_format;
74 	unsigned char		type;
75 	unsigned char		value_type;
76 	unsigned char		status;
77 	unsigned char		snmpv3_securitylevel;
78 	unsigned char		snmpv3_authprotocol;
79 	unsigned char		snmpv3_privprotocol;
80 	unsigned char		authtype;
81 	unsigned char		allow_traps;
82 	zbx_vector_ptr_t	lld_rows;
83 	zbx_vector_ptr_t	applications;
84 	zbx_vector_ptr_t	preproc_ops;
85 }
86 zbx_lld_item_prototype_t;
87 
88 #define	ZBX_DEPENDENT_ITEM_MAX_COUNT	999
89 #define	ZBX_DEPENDENT_ITEM_MAX_LEVELS	3
90 
91 typedef struct
92 {
93 	zbx_uint64_t		itemid;
94 	zbx_uint64_t		master_itemid;
95 	unsigned char		item_flags;
96 }
97 zbx_item_dependence_t;
98 
99 typedef struct
100 {
101 	zbx_uint64_t		itemid;
102 	zbx_uint64_t		parent_itemid;
103 	zbx_uint64_t		master_itemid;
104 #define ZBX_FLAG_LLD_ITEM_UNSET				__UINT64_C(0x0000000000000000)
105 #define ZBX_FLAG_LLD_ITEM_DISCOVERED			__UINT64_C(0x0000000000000001)
106 #define ZBX_FLAG_LLD_ITEM_UPDATE_NAME			__UINT64_C(0x0000000000000002)
107 #define ZBX_FLAG_LLD_ITEM_UPDATE_KEY			__UINT64_C(0x0000000000000004)
108 #define ZBX_FLAG_LLD_ITEM_UPDATE_TYPE			__UINT64_C(0x0000000000000008)
109 #define ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE		__UINT64_C(0x0000000000000010)
110 #define ZBX_FLAG_LLD_ITEM_UPDATE_DELAY			__UINT64_C(0x0000000000000040)
111 #define ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY		__UINT64_C(0x0000000000000100)
112 #define ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS			__UINT64_C(0x0000000000000200)
113 #define ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS		__UINT64_C(0x0000000000000400)
114 #define ZBX_FLAG_LLD_ITEM_UPDATE_UNITS			__UINT64_C(0x0000000000000800)
115 #define ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA		__UINT64_C(0x0000000000004000)
116 #define ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT		__UINT64_C(0x0000000000008000)
117 #define ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID		__UINT64_C(0x0000000000010000)
118 #define ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS			__UINT64_C(0x0000000000020000)
119 #define ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR		__UINT64_C(0x0000000000040000)
120 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY		__UINT64_C(0x0000000000080000)
121 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID		__UINT64_C(0x0000000000100000)
122 #define ZBX_FLAG_LLD_ITEM_UPDATE_PORT			__UINT64_C(0x0000000000200000)
123 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME	__UINT64_C(0x0000000000400000)
124 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL	__UINT64_C(0x0000000000800000)
125 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL	__UINT64_C(0x0000000001000000)
126 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE	__UINT64_C(0x0000000002000000)
127 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL	__UINT64_C(0x0000000004000000)
128 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE	__UINT64_C(0x0000000008000000)
129 #define ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE		__UINT64_C(0x0000000010000000)
130 #define ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME		__UINT64_C(0x0000000020000000)
131 #define ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD		__UINT64_C(0x0000000040000000)
132 #define ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY		__UINT64_C(0x0000000080000000)
133 #define ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY		__UINT64_C(0x0000000100000000)
134 #define ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION		__UINT64_C(0x0000000200000000)
135 #define ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID		__UINT64_C(0x0000000400000000)
136 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME	__UINT64_C(0x0000000800000000)
137 #define ZBX_FLAG_LLD_ITEM_UPDATE_JMX_ENDPOINT		__UINT64_C(0x0000001000000000)
138 #define ZBX_FLAG_LLD_ITEM_UPDATE_MASTER_ITEM		__UINT64_C(0x0000002000000000)
139 #define ZBX_FLAG_LLD_ITEM_UPDATE_TIMEOUT		__UINT64_C(0x0000004000000000)
140 #define ZBX_FLAG_LLD_ITEM_UPDATE_URL			__UINT64_C(0x0000008000000000)
141 #define ZBX_FLAG_LLD_ITEM_UPDATE_QUERY_FIELDS		__UINT64_C(0x0000010000000000)
142 #define ZBX_FLAG_LLD_ITEM_UPDATE_POSTS			__UINT64_C(0x0000020000000000)
143 #define ZBX_FLAG_LLD_ITEM_UPDATE_STATUS_CODES		__UINT64_C(0x0000040000000000)
144 #define ZBX_FLAG_LLD_ITEM_UPDATE_FOLLOW_REDIRECTS	__UINT64_C(0x0000080000000000)
145 #define ZBX_FLAG_LLD_ITEM_UPDATE_POST_TYPE		__UINT64_C(0x0000100000000000)
146 #define ZBX_FLAG_LLD_ITEM_UPDATE_HTTP_PROXY		__UINT64_C(0x0000200000000000)
147 #define ZBX_FLAG_LLD_ITEM_UPDATE_HEADERS		__UINT64_C(0x0000400000000000)
148 #define ZBX_FLAG_LLD_ITEM_UPDATE_RETRIEVE_MODE		__UINT64_C(0x0000800000000000)
149 #define ZBX_FLAG_LLD_ITEM_UPDATE_REQUEST_METHOD		__UINT64_C(0x0001000000000000)
150 #define ZBX_FLAG_LLD_ITEM_UPDATE_OUTPUT_FORMAT		__UINT64_C(0x0002000000000000)
151 #define ZBX_FLAG_LLD_ITEM_UPDATE_SSL_CERT_FILE		__UINT64_C(0x0004000000000000)
152 #define ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_FILE		__UINT64_C(0x0008000000000000)
153 #define ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_PASSWORD	__UINT64_C(0x0010000000000000)
154 #define ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_PEER		__UINT64_C(0x0020000000000000)
155 #define ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_HOST		__UINT64_C(0x0040000000000000)
156 #define ZBX_FLAG_LLD_ITEM_UPDATE_ALLOW_TRAPS		__UINT64_C(0x0080000000000000)
157 #define ZBX_FLAG_LLD_ITEM_UPDATE			(~ZBX_FLAG_LLD_ITEM_DISCOVERED)
158 	zbx_uint64_t		flags;
159 	char			*key_proto;
160 	char			*name;
161 	char			*name_proto;
162 	char			*key;
163 	char			*key_orig;
164 	char			*delay;
165 	char			*delay_orig;
166 	char			*history;
167 	char			*history_orig;
168 	char			*trends;
169 	char			*trends_orig;
170 	char			*units;
171 	char			*units_orig;
172 	char			*params;
173 	char			*params_orig;
174 	char			*username;
175 	char			*username_orig;
176 	char			*password;
177 	char			*password_orig;
178 	char			*ipmi_sensor;
179 	char			*ipmi_sensor_orig;
180 	char			*snmp_oid;
181 	char			*snmp_oid_orig;
182 	char			*description;
183 	char			*description_orig;
184 	char			*jmx_endpoint;
185 	char			*jmx_endpoint_orig;
186 	char			*timeout;
187 	char			*timeout_orig;
188 	char			*url;
189 	char			*url_orig;
190 	char			*query_fields;
191 	char			*query_fields_orig;
192 	char			*posts;
193 	char			*posts_orig;
194 	char			*status_codes;
195 	char			*status_codes_orig;
196 	char			*http_proxy;
197 	char			*http_proxy_orig;
198 	char			*headers;
199 	char			*headers_orig;
200 	char			*ssl_cert_file;
201 	char			*ssl_cert_file_orig;
202 	char			*ssl_key_file;
203 	char			*ssl_key_file_orig;
204 	char			*ssl_key_password;
205 	char			*ssl_key_password_orig;
206 	int			lastcheck;
207 	int			ts_delete;
208 	const zbx_lld_row_t	*lld_row;
209 	zbx_vector_ptr_t	preproc_ops;
210 	zbx_vector_ptr_t	dependent_items;
211 	unsigned char		type;
212 }
213 zbx_lld_item_t;
214 
215 typedef struct
216 {
217 	zbx_uint64_t	item_preprocid;
218 	int		step;
219 	int		type;
220 	char		*params;
221 
222 #define ZBX_FLAG_LLD_ITEM_PREPROC_UNSET				__UINT64_C(0x00)
223 #define ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED			__UINT64_C(0x01)
224 #define ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_TYPE			__UINT64_C(0x02)
225 #define ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_PARAMS			__UINT64_C(0x04)
226 #define ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_STEP			__UINT64_C(0x08)
227 #define ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE								\
228 		(ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_TYPE | ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_PARAMS |	\
229 		ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_STEP)
230 #define ZBX_FLAG_LLD_ITEM_PREPROC_DELETE				__UINT64_C(0x08)
231 	zbx_uint64_t	flags;
232 }
233 zbx_lld_item_preproc_t;
234 
235 /* item index by prototype (parent) id and lld row */
236 typedef struct
237 {
238 	zbx_uint64_t	parent_itemid;
239 	zbx_lld_row_t	*lld_row;
240 	zbx_lld_item_t	*item;
241 }
242 zbx_lld_item_index_t;
243 
244 typedef struct
245 {
246 	zbx_uint64_t	application_prototypeid;
247 	zbx_uint64_t	itemid;
248 	char		*name;
249 }
250 zbx_lld_application_prototype_t;
251 
252 typedef struct
253 {
254 	zbx_uint64_t		applicationid;
255 	zbx_uint64_t		application_prototypeid;
256 	zbx_uint64_t		application_discoveryid;
257 	int			lastcheck;
258 	int			ts_delete;
259 #define ZBX_FLAG_LLD_APPLICATION_UNSET			__UINT64_C(0x0000000000000000)
260 #define ZBX_FLAG_LLD_APPLICATION_DISCOVERED		__UINT64_C(0x0000000000000001)
261 #define ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME		__UINT64_C(0x0000000000000002)
262 #define ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY		__UINT64_C(0x0000000100000000)
263 #define ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY	__UINT64_C(0x0000000200000000)
264 #define ZBX_FLAG_LLD_APPLICATION_REMOVE			__UINT64_C(0x0000000400000000)
265 	zbx_uint64_t		flags;
266 	char			*name;
267 	char			*name_proto;
268 	char			*name_orig;
269 	const zbx_lld_row_t	*lld_row;
270 }
271 zbx_lld_application_t;
272 
273 /* reference to an item either by its id (existing items) or structure (new items) */
274 typedef struct
275 {
276 	zbx_uint64_t	itemid;
277 	zbx_lld_item_t	*item;
278 }
279 zbx_lld_item_ref_t;
280 
281 /* reference to an application either by its id (existing applications) or structure (new applications) */
282 typedef struct
283 {
284 	zbx_uint64_t		applicationid;
285 	zbx_lld_application_t	*application;
286 }
287 zbx_lld_application_ref_t;
288 
289 /* item prototype-application link reference by application id (existing applications) */
290 /* or application prototype structure (application prototypes)                         */
291 typedef struct
292 {
293 	zbx_lld_application_prototype_t	*application_prototype;
294 	zbx_uint64_t			applicationid;
295 }
296 zbx_lld_item_application_ref_t;
297 
298 /* item-application link */
299 typedef struct
300 {
301 	zbx_uint64_t			itemappid;
302 	zbx_lld_item_ref_t		item_ref;
303 	zbx_lld_application_ref_t	application_ref;
304 #define ZBX_FLAG_LLD_ITEM_APPLICATION_UNSET		__UINT64_C(0x0000000000000000)
305 #define ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED	__UINT64_C(0x0000000000000001)
306 	zbx_uint64_t			flags;
307 }
308 zbx_lld_item_application_t;
309 
310 /* application index by prototypeid and lld row */
311 typedef struct
312 {
313 	zbx_uint64_t		application_prototypeid;
314 	const zbx_lld_row_t	*lld_row;
315 	zbx_lld_application_t	*application;
316 }
317 zbx_lld_application_index_t;
318 
319 /* items index hashset support functions */
lld_item_index_hash_func(const void * data)320 static zbx_hash_t	lld_item_index_hash_func(const void *data)
321 {
322 	zbx_lld_item_index_t	*item_index = (zbx_lld_item_index_t *)data;
323 	zbx_hash_t		hash;
324 
325 	hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&item_index->parent_itemid,
326 			sizeof(item_index->parent_itemid), ZBX_DEFAULT_HASH_SEED);
327 	return ZBX_DEFAULT_PTR_HASH_ALGO(&item_index->lld_row, sizeof(item_index->lld_row), hash);
328 }
329 
lld_item_index_compare_func(const void * d1,const void * d2)330 static int	lld_item_index_compare_func(const void *d1, const void *d2)
331 {
332 	zbx_lld_item_index_t	*i1 = (zbx_lld_item_index_t *)d1;
333 	zbx_lld_item_index_t	*i2 = (zbx_lld_item_index_t *)d2;
334 
335 	ZBX_RETURN_IF_NOT_EQUAL(i1->parent_itemid, i2->parent_itemid);
336 	ZBX_RETURN_IF_NOT_EQUAL(i1->lld_row, i2->lld_row);
337 
338 	return 0;
339 }
340 
341 /* application index hashset support functions */
lld_application_index_hash_func(const void * data)342 static zbx_hash_t	lld_application_index_hash_func(const void *data)
343 {
344 	zbx_lld_application_index_t	*application_index = (zbx_lld_application_index_t *)data;
345 	zbx_hash_t			hash;
346 
347 	hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&application_index->application_prototypeid,
348 			sizeof(application_index->application_prototypeid), ZBX_DEFAULT_HASH_SEED);
349 	return ZBX_DEFAULT_PTR_HASH_ALGO(&application_index->lld_row, sizeof(application_index->lld_row), hash);
350 }
351 
lld_application_index_compare_func(const void * d1,const void * d2)352 static int	lld_application_index_compare_func(const void *d1, const void *d2)
353 {
354 	zbx_lld_application_index_t	*i1 = (zbx_lld_application_index_t *)d1;
355 	zbx_lld_application_index_t	*i2 = (zbx_lld_application_index_t *)d2;
356 
357 	ZBX_RETURN_IF_NOT_EQUAL(i1->application_prototypeid, i2->application_prototypeid);
358 	ZBX_RETURN_IF_NOT_EQUAL(i1->lld_row, i2->lld_row);
359 
360 	return 0;
361 }
362 
363 /* comparison function for discovered application lookup by name */
lld_application_compare_name(const void * d1,const void * d2)364 static int	lld_application_compare_name(const void *d1, const void *d2)
365 {
366 	const zbx_lld_application_t	*a1 = *(zbx_lld_application_t **)d1;
367 	const zbx_lld_application_t	*a2 = *(zbx_lld_application_t **)d2;
368 
369 	if (0 == (a1->flags & a2->flags))
370 		return -1;
371 
372 	if (NULL == a1->name || NULL == a2->name)
373 		return -1;
374 
375 	return strcmp(a1->name, a2->name);
376 }
377 
378 /* comparison function for discovered application lookup by original name name */
lld_application_compare_name_orig(const void * d1,const void * d2)379 static int	lld_application_compare_name_orig(const void *d1, const void *d2)
380 {
381 	const zbx_lld_application_t	*a1 = *(zbx_lld_application_t **)d1;
382 	const zbx_lld_application_t	*a2 = *(zbx_lld_application_t **)d2;
383 
384 	if (0 == (a1->flags & a2->flags))
385 		return -1;
386 
387 	if (NULL == a1->name_orig || NULL == a2->name_orig)
388 		return -1;
389 
390 	return strcmp(a1->name_orig, a2->name_orig);
391 }
392 
393 /* string pointer hashset (used to check for duplicate item keys) support functions */
lld_items_keys_hash_func(const void * data)394 static zbx_hash_t	lld_items_keys_hash_func(const void *data)
395 {
396 	return ZBX_DEFAULT_STRING_HASH_FUNC(*(char **)data);
397 }
398 
lld_items_keys_compare_func(const void * d1,const void * d2)399 static int	lld_items_keys_compare_func(const void *d1, const void *d2)
400 {
401 	return ZBX_DEFAULT_STR_COMPARE_FUNC(d1, d2);
402 }
403 
404 /* items - applications hashset support */
lld_item_application_hash_func(const void * data)405 static zbx_hash_t	lld_item_application_hash_func(const void *data)
406 {
407 	const zbx_lld_item_application_t	*item_application = (zbx_lld_item_application_t *)data;
408 	zbx_hash_t				hash;
409 
410 	hash = ZBX_DEFAULT_HASH_ALGO(&item_application->item_ref.itemid, sizeof(item_application->item_ref.itemid),
411 				ZBX_DEFAULT_HASH_SEED);
412 	hash = ZBX_DEFAULT_HASH_ALGO(&item_application->item_ref.item, sizeof(item_application->item_ref.item), hash);
413 
414 	hash = ZBX_DEFAULT_HASH_ALGO(&item_application->application_ref.applicationid,
415 			sizeof(item_application->application_ref.applicationid), hash);
416 	return ZBX_DEFAULT_HASH_ALGO(&item_application->application_ref.application,
417 			sizeof(item_application->application_ref.application), hash);
418 }
419 
lld_item_application_compare_func(const void * d1,const void * d2)420 static int	lld_item_application_compare_func(const void *d1, const void *d2)
421 {
422 	const zbx_lld_item_application_t	*ia1 = (zbx_lld_item_application_t *)d1;
423 	const zbx_lld_item_application_t	*ia2 = (zbx_lld_item_application_t *)d2;
424 
425 	ZBX_RETURN_IF_NOT_EQUAL(ia1->item_ref.itemid, ia2->item_ref.itemid);
426 	ZBX_RETURN_IF_NOT_EQUAL(ia1->item_ref.item, ia2->item_ref.item);
427 	ZBX_RETURN_IF_NOT_EQUAL(ia1->application_ref.applicationid, ia2->application_ref.applicationid);
428 	ZBX_RETURN_IF_NOT_EQUAL(ia1->application_ref.application, ia2->application_ref.application);
429 
430 	return 0;
431 }
432 
lld_item_preproc_sort_by_step(const void * d1,const void * d2)433 static int	lld_item_preproc_sort_by_step(const void *d1, const void *d2)
434 {
435 	zbx_lld_item_preproc_t	*op1 = *(zbx_lld_item_preproc_t **)d1;
436 	zbx_lld_item_preproc_t	*op2 = *(zbx_lld_item_preproc_t **)d2;
437 
438 	ZBX_RETURN_IF_NOT_EQUAL(op1->step, op2->step);
439 	return 0;
440 }
441 
lld_application_prototype_free(zbx_lld_application_prototype_t * application_prototype)442 static void	lld_application_prototype_free(zbx_lld_application_prototype_t *application_prototype)
443 {
444 	zbx_free(application_prototype->name);
445 	zbx_free(application_prototype);
446 }
447 
lld_application_free(zbx_lld_application_t * application)448 static void	lld_application_free(zbx_lld_application_t *application)
449 {
450 	zbx_free(application->name_orig);
451 	zbx_free(application->name_proto);
452 	zbx_free(application->name);
453 	zbx_free(application);
454 }
455 
lld_item_preproc_free(zbx_lld_item_preproc_t * op)456 static void	lld_item_preproc_free(zbx_lld_item_preproc_t *op)
457 {
458 	zbx_free(op->params);
459 	zbx_free(op);
460 }
461 
lld_item_prototype_free(zbx_lld_item_prototype_t * item_prototype)462 static void	lld_item_prototype_free(zbx_lld_item_prototype_t *item_prototype)
463 {
464 	zbx_free(item_prototype->name);
465 	zbx_free(item_prototype->key);
466 	zbx_free(item_prototype->delay);
467 	zbx_free(item_prototype->history);
468 	zbx_free(item_prototype->trends);
469 	zbx_free(item_prototype->trapper_hosts);
470 	zbx_free(item_prototype->units);
471 	zbx_free(item_prototype->formula);
472 	zbx_free(item_prototype->logtimefmt);
473 	zbx_free(item_prototype->params);
474 	zbx_free(item_prototype->ipmi_sensor);
475 	zbx_free(item_prototype->snmp_community);
476 	zbx_free(item_prototype->snmp_oid);
477 	zbx_free(item_prototype->snmpv3_securityname);
478 	zbx_free(item_prototype->snmpv3_authpassphrase);
479 	zbx_free(item_prototype->snmpv3_privpassphrase);
480 	zbx_free(item_prototype->snmpv3_contextname);
481 	zbx_free(item_prototype->username);
482 	zbx_free(item_prototype->password);
483 	zbx_free(item_prototype->publickey);
484 	zbx_free(item_prototype->privatekey);
485 	zbx_free(item_prototype->description);
486 	zbx_free(item_prototype->port);
487 	zbx_free(item_prototype->jmx_endpoint);
488 	zbx_free(item_prototype->timeout);
489 	zbx_free(item_prototype->url);
490 	zbx_free(item_prototype->query_fields);
491 	zbx_free(item_prototype->posts);
492 	zbx_free(item_prototype->status_codes);
493 	zbx_free(item_prototype->http_proxy);
494 	zbx_free(item_prototype->headers);
495 	zbx_free(item_prototype->ssl_cert_file);
496 	zbx_free(item_prototype->ssl_key_file);
497 	zbx_free(item_prototype->ssl_key_password);
498 
499 	zbx_vector_ptr_destroy(&item_prototype->lld_rows);
500 
501 	zbx_vector_ptr_clear_ext(&item_prototype->applications, zbx_default_mem_free_func);
502 	zbx_vector_ptr_destroy(&item_prototype->applications);
503 
504 	zbx_vector_ptr_clear_ext(&item_prototype->preproc_ops, (zbx_clean_func_t)lld_item_preproc_free);
505 	zbx_vector_ptr_destroy(&item_prototype->preproc_ops);
506 
507 	zbx_free(item_prototype);
508 }
509 
lld_item_free(zbx_lld_item_t * item)510 static void	lld_item_free(zbx_lld_item_t *item)
511 {
512 	zbx_free(item->key_proto);
513 	zbx_free(item->name);
514 	zbx_free(item->name_proto);
515 	zbx_free(item->key);
516 	zbx_free(item->key_orig);
517 	zbx_free(item->delay);
518 	zbx_free(item->delay_orig);
519 	zbx_free(item->history);
520 	zbx_free(item->history_orig);
521 	zbx_free(item->trends);
522 	zbx_free(item->trends_orig);
523 	zbx_free(item->units);
524 	zbx_free(item->units_orig);
525 	zbx_free(item->params);
526 	zbx_free(item->params_orig);
527 	zbx_free(item->ipmi_sensor);
528 	zbx_free(item->ipmi_sensor_orig);
529 	zbx_free(item->snmp_oid);
530 	zbx_free(item->snmp_oid_orig);
531 	zbx_free(item->username);
532 	zbx_free(item->username_orig);
533 	zbx_free(item->password);
534 	zbx_free(item->password_orig);
535 	zbx_free(item->description);
536 	zbx_free(item->description_orig);
537 	zbx_free(item->jmx_endpoint);
538 	zbx_free(item->jmx_endpoint_orig);
539 	zbx_free(item->timeout);
540 	zbx_free(item->timeout_orig);
541 	zbx_free(item->url);
542 	zbx_free(item->url_orig);
543 	zbx_free(item->query_fields);
544 	zbx_free(item->query_fields_orig);
545 	zbx_free(item->posts);
546 	zbx_free(item->posts_orig);
547 	zbx_free(item->status_codes);
548 	zbx_free(item->status_codes_orig);
549 	zbx_free(item->http_proxy);
550 	zbx_free(item->http_proxy_orig);
551 	zbx_free(item->headers);
552 	zbx_free(item->headers_orig);
553 	zbx_free(item->ssl_cert_file);
554 	zbx_free(item->ssl_cert_file_orig);
555 	zbx_free(item->ssl_key_file);
556 	zbx_free(item->ssl_key_file_orig);
557 	zbx_free(item->ssl_key_password);
558 	zbx_free(item->ssl_key_password_orig);
559 
560 	zbx_vector_ptr_clear_ext(&item->preproc_ops, (zbx_clean_func_t)lld_item_preproc_free);
561 	zbx_vector_ptr_destroy(&item->preproc_ops);
562 	zbx_vector_ptr_destroy(&item->dependent_items);
563 
564 	zbx_free(item);
565 }
566 
567 /******************************************************************************
568  *                                                                            *
569  * Function: lld_items_get                                                    *
570  *                                                                            *
571  * Purpose: retrieves existing items for the specified item prototypes        *
572  *                                                                            *
573  * Parameters: item_prototypes - [IN] item prototypes                         *
574  *             items           - [OUT] list of items                          *
575  *                                                                            *
576  ******************************************************************************/
lld_items_get(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * items)577 static void	lld_items_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *items)
578 {
579 	const char		*__function_name = "lld_items_get";
580 
581 	DB_RESULT			result;
582 	DB_ROW				row;
583 	zbx_lld_item_t			*item, *master;
584 	zbx_lld_item_preproc_t		*preproc_op;
585 	const zbx_lld_item_prototype_t	*item_prototype;
586 	zbx_uint64_t			db_valuemapid, db_interfaceid, itemid, master_itemid;
587 	zbx_vector_uint64_t		parent_itemids;
588 	int				i, index;
589 	char				*sql = NULL;
590 	size_t				sql_alloc = 0, sql_offset = 0;
591 
592 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
593 
594 	zbx_vector_uint64_create(&parent_itemids);
595 	zbx_vector_uint64_reserve(&parent_itemids, item_prototypes->values_num);
596 
597 	for (i = 0; i < item_prototypes->values_num; i++)
598 	{
599 		item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[i];
600 
601 		zbx_vector_uint64_append(&parent_itemids, item_prototype->itemid);
602 	}
603 
604 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
605 			"select id.itemid,id.key_,id.lastcheck,id.ts_delete,i.name,i.key_,i.type,i.value_type,"
606 				"i.delay,i.history,i.trends,i.trapper_hosts,i.units,"
607 				"i.formula,i.logtimefmt,i.valuemapid,i.params,i.ipmi_sensor,"
608 				"i.snmp_community,i.snmp_oid,i.port,i.snmpv3_securityname,i.snmpv3_securitylevel,"
609 				"i.snmpv3_authprotocol,i.snmpv3_authpassphrase,i.snmpv3_privprotocol,"
610 				"i.snmpv3_privpassphrase,i.authtype,i.username,i.password,i.publickey,i.privatekey,"
611 				"i.description,i.interfaceid,i.snmpv3_contextname,i.jmx_endpoint,i.master_itemid,"
612 				"i.timeout,i.url,i.query_fields,i.posts,i.status_codes,i.follow_redirects,i.post_type,"
613 				"i.http_proxy,i.headers,i.retrieve_mode,i.request_method,i.output_format,"
614 				"i.ssl_cert_file,i.ssl_key_file,i.ssl_key_password,i.verify_peer,i.verify_host,"
615 				"id.parent_itemid,i.allow_traps"
616 			" from item_discovery id"
617 				" join items i"
618 					" on id.itemid=i.itemid"
619 			" where");
620 
621 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "id.parent_itemid", parent_itemids.values,
622 			parent_itemids.values_num);
623 
624 	result = DBselect("%s", sql);
625 
626 	while (NULL != (row = DBfetch(result)))
627 	{
628 		ZBX_STR2UINT64(itemid, row[54]);
629 
630 		if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &itemid,
631 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
632 		{
633 			THIS_SHOULD_NEVER_HAPPEN;
634 			continue;
635 		}
636 
637 		item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[index];
638 
639 		item = (zbx_lld_item_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_t));
640 
641 		ZBX_STR2UINT64(item->itemid, row[0]);
642 		item->parent_itemid = itemid;
643 		item->key_proto = zbx_strdup(NULL, row[1]);
644 		item->lastcheck = atoi(row[2]);
645 		item->ts_delete = atoi(row[3]);
646 		item->name = zbx_strdup(NULL, row[4]);
647 		item->name_proto = NULL;
648 		item->key = zbx_strdup(NULL, row[5]);
649 		item->key_orig = NULL;
650 		item->flags = ZBX_FLAG_LLD_ITEM_UNSET;
651 
652 		item->type = item_prototype->type;
653 		if ((unsigned char)atoi(row[6]) != item_prototype->type)
654 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TYPE;
655 
656 		if ((unsigned char)atoi(row[7]) != item_prototype->value_type)
657 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE;
658 
659 		item->delay = zbx_strdup(NULL, row[8]);
660 		item->delay_orig = NULL;
661 
662 		item->history = zbx_strdup(NULL, row[9]);
663 		item->history_orig = NULL;
664 
665 		item->trends = zbx_strdup(NULL, row[10]);
666 		item->trends_orig = NULL;
667 
668 		if (0 != strcmp(row[11], item_prototype->trapper_hosts))
669 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS;
670 
671 		item->units = zbx_strdup(NULL, row[12]);
672 		item->units_orig = NULL;
673 
674 		if (0 != strcmp(row[13], item_prototype->formula))
675 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA;
676 
677 		if (0 != strcmp(row[14], item_prototype->logtimefmt))
678 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT;
679 
680 		ZBX_DBROW2UINT64(db_valuemapid, row[15]);
681 		if (db_valuemapid != item_prototype->valuemapid)
682 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID;
683 
684 		item->params = zbx_strdup(NULL, row[16]);
685 		item->params_orig = NULL;
686 
687 		item->ipmi_sensor = zbx_strdup(NULL, row[17]);
688 		item->ipmi_sensor_orig = NULL;
689 
690 		if (0 != strcmp(row[18], item_prototype->snmp_community))
691 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY;
692 
693 		item->snmp_oid = zbx_strdup(NULL, row[19]);
694 		item->snmp_oid_orig = NULL;
695 
696 		if (0 != strcmp(row[20], item_prototype->port))
697 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PORT;
698 
699 		if (0 != strcmp(row[21], item_prototype->snmpv3_securityname))
700 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME;
701 
702 		if ((unsigned char)atoi(row[22]) != item_prototype->snmpv3_securitylevel)
703 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL;
704 
705 		if ((unsigned char)atoi(row[23]) != item_prototype->snmpv3_authprotocol)
706 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL;
707 
708 		if (0 != strcmp(row[24], item_prototype->snmpv3_authpassphrase))
709 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE;
710 
711 		if ((unsigned char)atoi(row[25]) != item_prototype->snmpv3_privprotocol)
712 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL;
713 
714 		if (0 != strcmp(row[26], item_prototype->snmpv3_privpassphrase))
715 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE;
716 
717 		if ((unsigned char)atoi(row[27]) != item_prototype->authtype)
718 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE;
719 
720 		item->username = zbx_strdup(NULL, row[28]);
721 		item->username_orig = NULL;
722 
723 		item->password = zbx_strdup(NULL, row[29]);
724 		item->password_orig = NULL;
725 
726 		if (0 != strcmp(row[30], item_prototype->publickey))
727 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY;
728 
729 		if (0 != strcmp(row[31], item_prototype->privatekey))
730 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY;
731 
732 		item->description = zbx_strdup(NULL, row[32]);
733 		item->description_orig = NULL;
734 
735 		ZBX_DBROW2UINT64(db_interfaceid, row[33]);
736 		if (db_interfaceid != item_prototype->interfaceid)
737 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID;
738 
739 		if (0 != strcmp(row[34], item_prototype->snmpv3_contextname))
740 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME;
741 
742 		item->jmx_endpoint = zbx_strdup(NULL, row[35]);
743 		item->jmx_endpoint_orig = NULL;
744 
745 		ZBX_DBROW2UINT64(item->master_itemid, row[36]);
746 
747 		item->timeout = zbx_strdup(NULL, row[37]);
748 		item->timeout_orig = NULL;
749 
750 		item->url = zbx_strdup(NULL, row[38]);
751 		item->url_orig = NULL;
752 
753 		item->query_fields = zbx_strdup(NULL, row[39]);
754 		item->query_fields_orig = NULL;
755 
756 		item->posts = zbx_strdup(NULL, row[40]);
757 		item->posts_orig = NULL;
758 
759 		item->status_codes = zbx_strdup(NULL, row[41]);
760 		item->status_codes_orig = NULL;
761 
762 		if ((unsigned char)atoi(row[42]) != item_prototype->follow_redirects)
763 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_FOLLOW_REDIRECTS;
764 
765 		if ((unsigned char)atoi(row[43]) != item_prototype->post_type)
766 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_POST_TYPE;
767 
768 		item->http_proxy = zbx_strdup(NULL, row[44]);
769 		item->http_proxy_orig = NULL;
770 
771 		item->headers = zbx_strdup(NULL, row[45]);
772 		item->headers_orig = NULL;
773 
774 		if ((unsigned char)atoi(row[46]) != item_prototype->retrieve_mode)
775 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_RETRIEVE_MODE;
776 
777 		if ((unsigned char)atoi(row[47]) != item_prototype->request_method)
778 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_REQUEST_METHOD;
779 
780 		if ((unsigned char)atoi(row[48]) != item_prototype->output_format)
781 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_OUTPUT_FORMAT;
782 
783 		item->ssl_cert_file = zbx_strdup(NULL, row[49]);
784 		item->ssl_cert_file_orig = NULL;
785 
786 		item->ssl_key_file = zbx_strdup(NULL, row[50]);
787 		item->ssl_key_file_orig = NULL;
788 
789 		item->ssl_key_password = zbx_strdup(NULL, row[51]);
790 		item->ssl_key_password_orig = NULL;
791 
792 		if ((unsigned char)atoi(row[52]) != item_prototype->verify_peer)
793 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_PEER;
794 
795 		if ((unsigned char)atoi(row[53]) != item_prototype->verify_host)
796 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_HOST;
797 
798 		if ((unsigned char)atoi(row[55]) != item_prototype->allow_traps)
799 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_ALLOW_TRAPS;
800 
801 		item->lld_row = NULL;
802 
803 		zbx_vector_ptr_create(&item->preproc_ops);
804 		zbx_vector_ptr_create(&item->dependent_items);
805 
806 		zbx_vector_ptr_append(items, item);
807 	}
808 	DBfree_result(result);
809 
810 	zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
811 
812 	if (0 == items->values_num)
813 		goto out;
814 
815 	for (i = items->values_num - 1; i >= 0; i--)
816 	{
817 		item = (zbx_lld_item_t *)items->values[i];
818 		master_itemid = item->master_itemid;
819 
820 		if (0 != master_itemid && FAIL != (index = zbx_vector_ptr_bsearch(items, &master_itemid,
821 					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
822 		{
823 			/* dependent items based on prototypes should contain prototype itemid */
824 			master = (zbx_lld_item_t *)items->values[index];
825 			master_itemid = master->parent_itemid;
826 		}
827 
828 		if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
829 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
830 		{
831 			THIS_SHOULD_NEVER_HAPPEN;
832 			continue;
833 		}
834 
835 		item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[index];
836 
837 		if (master_itemid != item_prototype->master_itemid)
838 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_MASTER_ITEM;
839 
840 		item->master_itemid = item_prototype->master_itemid;
841 	}
842 
843 	sql_offset = 0;
844 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
845 			"select ip.item_preprocid,ip.itemid,ip.step,ip.type,ip.params"
846 			" from item_discovery id"
847 				" join item_preproc ip"
848 					" on id.itemid=ip.itemid"
849 			" where");
850 
851 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "id.parent_itemid", parent_itemids.values,
852 			parent_itemids.values_num);
853 
854 	result = DBselect("%s", sql);
855 
856 	while (NULL != (row = DBfetch(result)))
857 	{
858 		ZBX_STR2UINT64(itemid, row[1]);
859 
860 		if (FAIL == (index = zbx_vector_ptr_bsearch(items, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
861 		{
862 			THIS_SHOULD_NEVER_HAPPEN;
863 			continue;
864 		}
865 
866 		item = (zbx_lld_item_t *)items->values[index];
867 
868 		preproc_op = (zbx_lld_item_preproc_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_preproc_t));
869 		preproc_op->flags = ZBX_FLAG_LLD_ITEM_PREPROC_UNSET;
870 		ZBX_STR2UINT64(preproc_op->item_preprocid, row[0]);
871 		preproc_op->step = atoi(row[2]);
872 		preproc_op->type = atoi(row[3]);
873 		preproc_op->params = zbx_strdup(NULL, row[4]);
874 		zbx_vector_ptr_append(&item->preproc_ops, preproc_op);
875 	}
876 	DBfree_result(result);
877 out:
878 	zbx_free(sql);
879 	zbx_vector_uint64_destroy(&parent_itemids);
880 
881 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
882 }
883 
884 /******************************************************************************
885  *                                                                            *
886  * Function: is_user_macro                                                    *
887  *                                                                            *
888  * Purpose: checks if string is user macro                                    *
889  *                                                                            *
890  * Parameters: str - [IN] string to validate                                  *
891  *                                                                            *
892  * Returns: SUCCEED - either "{$MACRO}" or "{$MACRO:"{#MACRO}"}"              *
893  *          FAIL    - not user macro or contains other characters for example:*
894  *                    "dummy{$MACRO}", "{$MACRO}dummy" or "{$MACRO}{$MACRO}"  *
895  *                                                                            *
896  ******************************************************************************/
is_user_macro(const char * str)897 static int	is_user_macro(const char *str)
898 {
899 	zbx_token_t	token;
900 
901 	if (FAIL == zbx_token_find(str, 0, &token, ZBX_TOKEN_SEARCH_BASIC) ||
902 			0 == (token.type & ZBX_TOKEN_USER_MACRO) ||
903 			0 != token.loc.l || '\0' != str[token.loc.r + 1])
904 	{
905 		return FAIL;
906 	}
907 
908 	return SUCCEED;
909 }
910 
911 /******************************************************************************
912  *                                                                            *
913  * Function: lld_validate_item_field                                          *
914  *                                                                            *
915  ******************************************************************************/
lld_validate_item_field(zbx_lld_item_t * item,char ** field,char ** field_orig,zbx_uint64_t flag,size_t field_len,char ** error)916 static void	lld_validate_item_field(zbx_lld_item_t *item, char **field, char **field_orig, zbx_uint64_t flag,
917 		size_t field_len, char **error)
918 {
919 	if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
920 		return;
921 
922 	/* only new items or items with changed data or item type will be validated */
923 	if (0 != item->itemid && 0 == (item->flags & flag) && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TYPE))
924 		return;
925 
926 	if (SUCCEED != zbx_is_utf8(*field))
927 	{
928 		zbx_replace_invalid_utf8(*field);
929 		*error = zbx_strdcatf(*error, "Cannot %s item: value \"%s\" has invalid UTF-8 sequence.\n",
930 				(0 != item->itemid ? "update" : "create"), *field);
931 	}
932 	else if (zbx_strlen_utf8(*field) > field_len)
933 	{
934 		*error = zbx_strdcatf(*error, "Cannot %s item: value \"%s\" is too long.\n",
935 				(0 != item->itemid ? "update" : "create"), *field);
936 	}
937 	else
938 	{
939 		int	value;
940 		char	*errmsg = NULL;
941 
942 		switch (flag)
943 		{
944 			case ZBX_FLAG_LLD_ITEM_UPDATE_NAME:
945 				if ('\0' != **field)
946 					return;
947 
948 				*error = zbx_strdcatf(*error, "Cannot %s item: name is empty.\n",
949 						(0 != item->itemid ? "update" : "create"));
950 				break;
951 			case ZBX_FLAG_LLD_ITEM_UPDATE_DELAY:
952 				switch (item->type)
953 				{
954 					case ITEM_TYPE_TRAPPER:
955 					case ITEM_TYPE_SNMPTRAP:
956 					case ITEM_TYPE_DEPENDENT:
957 						return;
958 				}
959 
960 				if (SUCCEED == zbx_validate_interval(*field, &errmsg))
961 					return;
962 
963 				*error = zbx_strdcatf(*error, "Cannot %s item: %s\n",
964 						(0 != item->itemid ? "update" : "create"), errmsg);
965 				zbx_free(errmsg);
966 
967 				/* delay alone cannot be rolled back as it depends on item type, revert all updates */
968 				if (0 != item->itemid)
969 				{
970 					item->flags &= ZBX_FLAG_LLD_ITEM_DISCOVERED;
971 					return;
972 				}
973 				break;
974 			case ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY:
975 				if (SUCCEED == is_user_macro(*field))
976 					return;
977 
978 				if (SUCCEED == is_time_suffix(*field, &value, ZBX_LENGTH_UNLIMITED) && (0 == value ||
979 						(ZBX_HK_HISTORY_MIN <= value && ZBX_HK_PERIOD_MAX >= value)))
980 				{
981 					return;
982 				}
983 
984 				*error = zbx_strdcatf(*error, "Cannot %s item: invalid history storage period"
985 						" \"%s\".\n", (0 != item->itemid ? "update" : "create"), *field);
986 				break;
987 			case ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS:
988 				if (SUCCEED == is_user_macro(*field))
989 					return;
990 
991 				if (SUCCEED == is_time_suffix(*field, &value, ZBX_LENGTH_UNLIMITED) && (0 == value ||
992 						(ZBX_HK_TRENDS_MIN <= value && ZBX_HK_PERIOD_MAX >= value)))
993 				{
994 					return;
995 				}
996 
997 				*error = zbx_strdcatf(*error, "Cannot %s item: invalid trends storage period"
998 						" \"%s\".\n", (0 != item->itemid ? "update" : "create"), *field);
999 				break;
1000 			default:
1001 				return;
1002 		}
1003 	}
1004 
1005 	if (0 != item->itemid)
1006 		lld_field_str_rollback(field, field_orig, &item->flags, flag);
1007 	else
1008 		item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1009 }
1010 
1011 /******************************************************************************
1012  *                                                                            *
1013  * Function: lld_item_dependence_add                                          *
1014  *                                                                            *
1015  * Purpose: add a new dependency                                              *
1016  *                                                                            *
1017  * Parameters: item_dependencies - [IN\OUT] list of dependencies              *
1018  *             itemid            - [IN] item id                               *
1019  *             master_itemid     - [IN] master item id                        *
1020  *             item_flags        - [IN] item flags (ZBX_FLAG_DISCOVERY_*)     *
1021  *                                                                            *
1022  * Returns: item dependence                                                   *
1023  *                                                                            *
1024  * Comments: Memory is allocated to store item dependence. This memory must   *
1025  *           be freed by the caller.                                          *
1026  *                                                                            *
1027  ******************************************************************************/
lld_item_dependence_add(zbx_vector_ptr_t * item_dependencies,zbx_uint64_t itemid,zbx_uint64_t master_itemid,unsigned int item_flags)1028 static zbx_item_dependence_t	*lld_item_dependence_add(zbx_vector_ptr_t *item_dependencies, zbx_uint64_t itemid,
1029 		zbx_uint64_t master_itemid, unsigned int item_flags)
1030 {
1031 	zbx_item_dependence_t	*dependence = (zbx_item_dependence_t *)zbx_malloc(NULL, sizeof(zbx_item_dependence_t));
1032 
1033 	dependence->itemid = itemid;
1034 	dependence->master_itemid = master_itemid;
1035 	dependence->item_flags = item_flags;
1036 
1037 	zbx_vector_ptr_append(item_dependencies, dependence);
1038 
1039 	return dependence;
1040 }
1041 
1042 /******************************************************************************
1043  *                                                                            *
1044  * Function: lld_item_dependencies_get                                        *
1045  *                                                                            *
1046  * Purpose: recursively get dependencies with dependent items taking into     *
1047  *          account item prototypes                                           *
1048  *                                                                            *
1049  * Parameters: item_prototypes   - [IN] item prototypes                       *
1050  *             item_dependencies - [OUT] list of dependencies                 *
1051  *                                                                            *
1052  ******************************************************************************/
lld_item_dependencies_get(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * item_dependencies)1053 static void	lld_item_dependencies_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *item_dependencies)
1054 {
1055 #define NEXT_CHECK_BY_ITEM_IDS		0
1056 #define NEXT_CHECK_BY_MASTERITEM_IDS	1
1057 
1058 	const char		*__function_name = "lld_item_dependencies_get";
1059 
1060 	int			i, check_type;
1061 	zbx_vector_uint64_t	processed_masterid, processed_itemid, next_check_itemids, next_check_masterids,
1062 				*check_ids;
1063 	char			*sql = NULL;
1064 	size_t			sql_alloc = 0, sql_offset;
1065 	DB_RESULT		result;
1066 	DB_ROW			row;
1067 
1068 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1069 
1070 	zbx_vector_uint64_create(&processed_masterid);
1071 	zbx_vector_uint64_create(&processed_itemid);
1072 	zbx_vector_uint64_create(&next_check_itemids);
1073 	zbx_vector_uint64_create(&next_check_masterids);
1074 
1075 	/* collect the item id of prototypes for searching dependencies into database */
1076 	for (i = 0; i < item_prototypes->values_num; i++)
1077 	{
1078 		const zbx_lld_item_prototype_t	*item_prototype;
1079 
1080 		item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[i];
1081 
1082 		if (0 != item_prototype->master_itemid)
1083 		{
1084 			lld_item_dependence_add(item_dependencies, item_prototype->itemid,
1085 					item_prototype->master_itemid, ZBX_FLAG_DISCOVERY_PROTOTYPE);
1086 			zbx_vector_uint64_append(&next_check_itemids, item_prototype->master_itemid);
1087 			zbx_vector_uint64_append(&next_check_masterids, item_prototype->master_itemid);
1088 		}
1089 	}
1090 
1091 	/* search dependency in two directions (masteritem_id->itemid and itemid->masteritem_id) */
1092 	while (0 < next_check_itemids.values_num || 0 < next_check_masterids.values_num)
1093 	{
1094 		if (0 < next_check_itemids.values_num)
1095 		{
1096 			check_type = NEXT_CHECK_BY_ITEM_IDS;
1097 			check_ids = &next_check_itemids;
1098 		}
1099 		else
1100 		{
1101 			check_type = NEXT_CHECK_BY_MASTERITEM_IDS;
1102 			check_ids = &next_check_masterids;
1103 		}
1104 
1105 		sql_offset = 0;
1106 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select itemid,master_itemid,flags from items where");
1107 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset,
1108 				NEXT_CHECK_BY_ITEM_IDS == check_type ? "itemid" : "master_itemid",
1109 				check_ids->values, check_ids->values_num);
1110 
1111 		if (NEXT_CHECK_BY_ITEM_IDS == check_type)
1112 			zbx_vector_uint64_append_array(&processed_itemid, check_ids->values, check_ids->values_num);
1113 		else
1114 			zbx_vector_uint64_append_array(&processed_masterid, check_ids->values, check_ids->values_num);
1115 
1116 		zbx_vector_uint64_clear(check_ids);
1117 
1118 		result = DBselect("%s", sql);
1119 
1120 		while (NULL != (row = DBfetch(result)))
1121 		{
1122 			zbx_item_dependence_t	*dependence = NULL;
1123 			zbx_uint64_t		itemid, master_itemid;
1124 			unsigned int		item_flags;
1125 
1126 			ZBX_STR2UINT64(itemid, row[0]);
1127 			ZBX_DBROW2UINT64(master_itemid, row[1]);
1128 			ZBX_STR2UCHAR(item_flags, row[2]);
1129 
1130 			for (i = 0; i < item_dependencies->values_num; i++)
1131 			{
1132 				dependence = (zbx_item_dependence_t *)item_dependencies->values[i];
1133 				if (dependence->itemid == itemid && dependence->master_itemid == master_itemid)
1134 					break;
1135 			}
1136 
1137 			if (i == item_dependencies->values_num)
1138 			{
1139 				dependence = lld_item_dependence_add(item_dependencies, itemid, master_itemid,
1140 						item_flags);
1141 			}
1142 
1143 			if (FAIL == zbx_vector_uint64_search(&processed_masterid, dependence->itemid,
1144 					ZBX_DEFAULT_UINT64_COMPARE_FUNC))
1145 			{
1146 				zbx_vector_uint64_append(&next_check_masterids, dependence->itemid);
1147 			}
1148 
1149 			if (NEXT_CHECK_BY_ITEM_IDS != check_type || 0 == dependence->master_itemid)
1150 				continue;
1151 
1152 			if (FAIL == zbx_vector_uint64_search(&processed_itemid, dependence->master_itemid,
1153 					ZBX_DEFAULT_UINT64_COMPARE_FUNC))
1154 			{
1155 				zbx_vector_uint64_append(&next_check_itemids, dependence->master_itemid);
1156 			}
1157 		}
1158 		DBfree_result(result);
1159 	}
1160 	zbx_free(sql);
1161 
1162 	zbx_vector_uint64_destroy(&processed_masterid);
1163 	zbx_vector_uint64_destroy(&processed_itemid);
1164 	zbx_vector_uint64_destroy(&next_check_itemids);
1165 	zbx_vector_uint64_destroy(&next_check_masterids);
1166 
1167 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1168 
1169 #undef NEXT_CHECK_BY_ITEM_IDS
1170 #undef NEXT_CHECK_BY_MASTERITEM_IDS
1171 }
1172 
1173 /******************************************************************************
1174  *                                                                            *
1175  * Function: lld_item_dependencies_count                                      *
1176  *                                                                            *
1177  * Purpose: recursively count the number of dependencies                      *
1178  *                                                                            *
1179  * Parameters: itemid            - [IN] item ID to be checked                 *
1180  *             dependencies      - [IN] item dependencies                     *
1181  *             processed_itemids - [IN\OUT] list of checked item ids          *
1182  *             dependencies_num  - [IN\OUT] number of dependencies            *
1183  *             depth_level       - [IN\OUT] depth level                       *
1184  *                                                                            *
1185  * Returns: SUCCEED - the number of dependencies was successfully counted     *
1186  *          FAIL    - the limit of dependencies is reached                    *
1187  *                                                                            *
1188  ******************************************************************************/
lld_item_dependencies_count(const zbx_uint64_t itemid,const zbx_vector_ptr_t * dependencies,zbx_vector_uint64_t * processed_itemids,int * dependencies_num,unsigned char * depth_level)1189 static int	lld_item_dependencies_count(const zbx_uint64_t itemid, const zbx_vector_ptr_t *dependencies,
1190 		zbx_vector_uint64_t *processed_itemids, int *dependencies_num, unsigned char *depth_level)
1191 {
1192 	int	ret = FAIL, i, curr_depth_calculated = 0;
1193 
1194 	for (i = 0; i < dependencies->values_num; i++)
1195 	{
1196 		zbx_item_dependence_t	*dep = (zbx_item_dependence_t *)dependencies->values[i];
1197 
1198 		/* check if item is a master for someone else */
1199 		if (dep->master_itemid != itemid)
1200 			continue;
1201 
1202 		/* check the limit of dependent items */
1203 		if (0 == (dep->item_flags & ZBX_FLAG_DISCOVERY_PROTOTYPE) &&
1204 				ZBX_DEPENDENT_ITEM_MAX_COUNT <= ++(*dependencies_num))
1205 		{
1206 			goto out;
1207 		}
1208 
1209 		/* check the depth level */
1210 		if (0 == curr_depth_calculated)
1211 		{
1212 			curr_depth_calculated = 1;
1213 
1214 			if (ZBX_DEPENDENT_ITEM_MAX_LEVELS < ++(*depth_level))
1215 			{
1216 				/* API shouldn't allow to create dependencies deeper */
1217 				THIS_SHOULD_NEVER_HAPPEN;
1218 				goto out;
1219 			}
1220 		}
1221 
1222 		/* check if item was calculated in previous iterations */
1223 		if (FAIL != zbx_vector_uint64_search(processed_itemids, dep->itemid, ZBX_DEFAULT_UINT64_COMPARE_FUNC))
1224 			continue;
1225 
1226 		if (SUCCEED != lld_item_dependencies_count(dep->itemid, dependencies, processed_itemids,
1227 				dependencies_num, depth_level))
1228 		{
1229 			goto out;
1230 		}
1231 
1232 		/* add counted item id */
1233 		zbx_vector_uint64_append(processed_itemids, dep->itemid);
1234 	}
1235 
1236 	ret = SUCCEED;
1237 out:
1238 	if (1 == curr_depth_calculated)
1239 		(*depth_level)--;
1240 
1241 	return ret;
1242 }
1243 
1244 /******************************************************************************
1245  *                                                                            *
1246  * Function: lld_item_dependencies_check                                      *
1247  *                                                                            *
1248  * Purpose: check the limits of dependent items                               *
1249  *                                                                            *
1250  * Parameters: item             - [IN] discovered item                        *
1251  *             item_prototype   - [IN] item prototype to be checked for limit *
1252  *             dependencies     - [IN] item dependencies                      *
1253  *                                                                            *
1254  * Returns: SUCCEED - the check was successful                                *
1255  *          FAIL    - the limit of dependencies is exceeded                   *
1256  *                                                                            *
1257  ******************************************************************************/
lld_item_dependencies_check(const zbx_lld_item_t * item,const zbx_lld_item_prototype_t * item_prototype,zbx_vector_ptr_t * dependencies)1258 static int	lld_item_dependencies_check(const zbx_lld_item_t *item, const zbx_lld_item_prototype_t *item_prototype,
1259 		zbx_vector_ptr_t *dependencies)
1260 {
1261 	zbx_item_dependence_t	*dependence = NULL, *top_dependence = NULL, *tmp_dep;
1262 	int 			ret = FAIL, i, dependence_num = 0, item_in_deps = FAIL;
1263 	unsigned char		depth_level = 0;
1264 	zbx_vector_uint64_t	processed_itemids;
1265 
1266 	/* find the dependency of the item by item id */
1267 	for (i = 0; i < dependencies->values_num; i++)
1268 	{
1269 		dependence = (zbx_item_dependence_t *)dependencies->values[i];
1270 		if (item_prototype->itemid == dependence->itemid)
1271 			break;
1272 	}
1273 
1274 	if (NULL == dependence || i == dependencies->values_num)
1275 		return SUCCEED;
1276 
1277 	/* find the top dependency that doesn't have a master item id */
1278 	while (NULL == top_dependence)
1279 	{
1280 		for (i = 0; i < dependencies->values_num; i++)
1281 		{
1282 			tmp_dep = (zbx_item_dependence_t *)dependencies->values[i];
1283 
1284 			if (item->itemid == tmp_dep->itemid)
1285 				item_in_deps = SUCCEED;
1286 
1287 			if (dependence->master_itemid == tmp_dep->itemid)
1288 			{
1289 				dependence = tmp_dep;
1290 				break;
1291 			}
1292 		}
1293 
1294 		if (0 == dependence->master_itemid)
1295 		{
1296 			top_dependence = dependence;
1297 		}
1298 		else if (ZBX_DEPENDENT_ITEM_MAX_LEVELS < ++depth_level)
1299 		{
1300 			/* API shouldn't allow to create dependencies deeper than ZBX_DEPENDENT_ITEM_MAX_LEVELS */
1301 			THIS_SHOULD_NEVER_HAPPEN;
1302 			goto out;
1303 		}
1304 	}
1305 
1306 	depth_level = 0;
1307 	zbx_vector_uint64_create(&processed_itemids);
1308 
1309 	ret = lld_item_dependencies_count(top_dependence->itemid, dependencies, &processed_itemids, &dependence_num,
1310 			&depth_level);
1311 
1312 	zbx_vector_uint64_destroy(&processed_itemids);
1313 
1314 	if (SUCCEED == ret && SUCCEED != item_in_deps
1315 			&& 0 == (top_dependence->item_flags & ZBX_FLAG_DISCOVERY_PROTOTYPE))
1316 	{
1317 		lld_item_dependence_add(dependencies, item_prototype->itemid, item->master_itemid,
1318 				ZBX_FLAG_DISCOVERY_CREATED);
1319 	}
1320 
1321 out:
1322 	return ret;
1323 }
1324 
1325 /******************************************************************************
1326  *                                                                            *
1327  * Function: lld_items_preproc_step_validate                                  *
1328  *                                                                            *
1329  * Purpose: validation of a item preprocessing step expressions for discovery *
1330  *          process                                                           *
1331  *                                                                            *
1332  * Parameters: pp       - [IN] the item preprocessing step                    *
1333  *             itemid   - [IN] item ID for logging                            *
1334  *             error    - [IN/OUT] the lld error message                      *
1335  *                                                                            *
1336  * Return value: SUCCEED - if preprocessing step is valid                     *
1337  *               FAIL    - if preprocessing step is not valid                 *
1338  *                                                                            *
1339  ******************************************************************************/
lld_items_preproc_step_validate(const zbx_lld_item_preproc_t * pp,zbx_uint64_t itemid,char ** error)1340 static int	lld_items_preproc_step_validate(const zbx_lld_item_preproc_t * pp, zbx_uint64_t itemid, char ** error)
1341 {
1342 	int		ret = SUCCEED;
1343 	zbx_token_t	token;
1344 	char		err[MAX_STRING_LEN];
1345 	char		pattern[ITEM_PREPROC_PARAMS_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1], *output;
1346 	const char*	regexp_err = NULL;
1347 	zbx_jsonpath_t	jsonpath;
1348 
1349 	*err = '\0';
1350 
1351 	if (0 == (pp->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE)
1352 			|| (SUCCEED == zbx_token_find(pp->params, 0, &token, ZBX_TOKEN_SEARCH_BASIC)
1353 			&& 0 != (token.type & ZBX_TOKEN_USER_MACRO)))
1354 	{
1355 		return SUCCEED;
1356 	}
1357 
1358 	switch (pp->type)
1359 	{
1360 		case ZBX_PREPROC_REGSUB:
1361 			zbx_strlcpy(pattern, pp->params, sizeof(pattern));
1362 			if (NULL == (output = strchr(pattern, '\n')))
1363 			{
1364 				zbx_snprintf(err, sizeof(err), "cannot find second parameter: %s", pp->params);
1365 				ret = FAIL;
1366 				break;
1367 			}
1368 
1369 			*output++ = '\0';
1370 
1371 			if (FAIL == (ret = zbx_regexp_compile(pattern, NULL, &regexp_err)))
1372 			{
1373 				zbx_strlcpy(err, regexp_err, sizeof(err));
1374 			}
1375 			break;
1376 		case ZBX_PREPROC_JSONPATH:
1377 			if (FAIL == (ret = zbx_jsonpath_compile(pp->params, &jsonpath)))
1378 				zbx_strlcpy(err, zbx_json_strerror(), sizeof(err));
1379 			else
1380 				zbx_jsonpath_clear(&jsonpath);
1381 			break;
1382 		case ZBX_PREPROC_XPATH:
1383 			ret = xml_xpath_check(pp->params, err, sizeof(err));
1384 			break;
1385 		case ZBX_PREPROC_MULTIPLIER:
1386 			if (FAIL == (ret = is_double(pp->params, NULL)))
1387 				zbx_snprintf(err, sizeof(err), "value is not numeric or out of range: %s", pp->params);
1388 			break;
1389 	}
1390 
1391 	if (SUCCEED != ret)
1392 	{
1393 		*error = zbx_strdcatf(*error, "Cannot %s item: invalid value for preprocessing step #%d: %s.\n",
1394 				(0 != itemid ? "update" : "create"), pp->step, err);
1395 	}
1396 
1397 	return ret;
1398 }
1399 
1400 /******************************************************************************
1401  *                                                                            *
1402  * Function: lld_items_validate                                               *
1403  *                                                                            *
1404  * Parameters: hostid            - [IN] host id                               *
1405  *             items             - [IN] list of items                         *
1406  *             item_prototypes   - [IN] the item prototypes                   *
1407  *             item_dependencies - [IN] list of dependencies                  *
1408  *             error             - [IN/OUT] the lld error message             *
1409  *                                                                            *
1410  *****************************************************************************/
lld_items_validate(zbx_uint64_t hostid,zbx_vector_ptr_t * items,zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * item_dependencies,char ** error)1411 static void	lld_items_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *items, zbx_vector_ptr_t *item_prototypes,
1412 		zbx_vector_ptr_t *item_dependencies, char **error)
1413 {
1414 	const char			*__function_name = "lld_items_validate";
1415 
1416 	DB_RESULT			result;
1417 	DB_ROW				row;
1418 	int				i, j;
1419 	zbx_lld_item_t			*item;
1420 	zbx_vector_uint64_t		itemids;
1421 	zbx_vector_str_t		keys;
1422 	zbx_hashset_t			items_keys;
1423 
1424 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1425 
1426 	zbx_vector_uint64_create(&itemids);
1427 	zbx_vector_str_create(&keys);		/* list of item keys */
1428 
1429 	/* check an item name validity */
1430 	for (i = 0; i < items->values_num; i++)
1431 	{
1432 		item = (zbx_lld_item_t *)items->values[i];
1433 
1434 		lld_validate_item_field(item, &item->name, &item->name_proto,
1435 				ZBX_FLAG_LLD_ITEM_UPDATE_NAME, ITEM_NAME_LEN, error);
1436 		lld_validate_item_field(item, &item->key, &item->key_orig,
1437 				ZBX_FLAG_LLD_ITEM_UPDATE_KEY, ITEM_KEY_LEN, error);
1438 		lld_validate_item_field(item, &item->delay, &item->delay_orig,
1439 				ZBX_FLAG_LLD_ITEM_UPDATE_DELAY, ITEM_DELAY_LEN, error);
1440 		lld_validate_item_field(item, &item->history, &item->history_orig,
1441 				ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY, ITEM_HISTORY_LEN, error);
1442 		lld_validate_item_field(item, &item->trends, &item->trends_orig,
1443 				ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS, ITEM_TRENDS_LEN, error);
1444 		lld_validate_item_field(item, &item->units, &item->units_orig,
1445 				ZBX_FLAG_LLD_ITEM_UPDATE_UNITS, ITEM_UNITS_LEN, error);
1446 		lld_validate_item_field(item, &item->params, &item->params_orig,
1447 				ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS, ITEM_PARAM_LEN, error);
1448 		lld_validate_item_field(item, &item->ipmi_sensor, &item->ipmi_sensor_orig,
1449 				ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR, ITEM_IPMI_SENSOR_LEN, error);
1450 		lld_validate_item_field(item, &item->snmp_oid, &item->snmp_oid_orig,
1451 				ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID, ITEM_SNMP_OID_LEN, error);
1452 		lld_validate_item_field(item, &item->username, &item->username_orig,
1453 				ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME, ITEM_USERNAME_LEN, error);
1454 		lld_validate_item_field(item, &item->password, &item->password_orig,
1455 				ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD, ITEM_PASSWORD_LEN, error);
1456 		lld_validate_item_field(item, &item->description, &item->description_orig,
1457 				ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION, ITEM_DESCRIPTION_LEN, error);
1458 		lld_validate_item_field(item, &item->jmx_endpoint, &item->jmx_endpoint_orig,
1459 				ZBX_FLAG_LLD_ITEM_UPDATE_JMX_ENDPOINT, ITEM_JMX_ENDPOINT_LEN, error);
1460 		lld_validate_item_field(item, &item->timeout, &item->timeout_orig,
1461 				ZBX_FLAG_LLD_ITEM_UPDATE_TIMEOUT, ITEM_TIMEOUT_LEN, error);
1462 		lld_validate_item_field(item, &item->url, &item->url_orig,
1463 				ZBX_FLAG_LLD_ITEM_UPDATE_URL, ITEM_URL_LEN, error);
1464 		lld_validate_item_field(item, &item->query_fields, &item->query_fields_orig,
1465 				ZBX_FLAG_LLD_ITEM_UPDATE_QUERY_FIELDS, ITEM_QUERY_FIELDS_LEN, error);
1466 		lld_validate_item_field(item, &item->posts, &item->posts_orig,
1467 				ZBX_FLAG_LLD_ITEM_UPDATE_POSTS, ITEM_POSTS_LEN, error);
1468 		lld_validate_item_field(item, &item->status_codes, &item->status_codes_orig,
1469 				ZBX_FLAG_LLD_ITEM_UPDATE_STATUS_CODES, ITEM_STATUS_CODES_LEN, error);
1470 		lld_validate_item_field(item, &item->http_proxy, &item->http_proxy_orig,
1471 				ZBX_FLAG_LLD_ITEM_UPDATE_HTTP_PROXY, ITEM_HTTP_PROXY_LEN, error);
1472 		lld_validate_item_field(item, &item->headers, &item->headers_orig,
1473 				ZBX_FLAG_LLD_ITEM_UPDATE_HEADERS, ITEM_HEADERS_LEN, error);
1474 		lld_validate_item_field(item, &item->ssl_cert_file, &item->ssl_cert_file_orig,
1475 				ZBX_FLAG_LLD_ITEM_UPDATE_SSL_CERT_FILE, ITEM_SSL_CERT_FILE_LEN, error);
1476 		lld_validate_item_field(item, &item->ssl_key_file, &item->ssl_key_file_orig,
1477 				ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_FILE, ITEM_SSL_KEY_FILE_LEN, error);
1478 		lld_validate_item_field(item, &item->ssl_key_password, &item->ssl_key_password_orig,
1479 				ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_PASSWORD, ITEM_SSL_KEY_PASSWORD_LEN, error);
1480 	}
1481 
1482 	/* check duplicated item keys */
1483 
1484 	zbx_hashset_create(&items_keys, items->values_num, lld_items_keys_hash_func, lld_items_keys_compare_func);
1485 
1486 	/* add 'good' (existing, discovered and not updated) keys to the hashset */
1487 	for (i = 0; i < items->values_num; i++)
1488 	{
1489 		item = (zbx_lld_item_t *)items->values[i];
1490 
1491 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1492 			continue;
1493 
1494 		/* skip new or updated item keys */
1495 		if (0 == item->itemid || 0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
1496 			continue;
1497 
1498 		zbx_hashset_insert(&items_keys, &item->key, sizeof(char *));
1499 	}
1500 
1501 	/* check new and updated keys for duplicated keys in discovered items */
1502 	for (i = 0; i < items->values_num; i++)
1503 	{
1504 		item = (zbx_lld_item_t *)items->values[i];
1505 
1506 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1507 			continue;
1508 
1509 		/* only new items or items with changed key will be validated */
1510 		if (0 != item->itemid && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
1511 			continue;
1512 
1513 		if (NULL != zbx_hashset_search(&items_keys, &item->key))
1514 		{
1515 			*error = zbx_strdcatf(*error, "Cannot %s item: item with the same key \"%s\" already exists.\n",
1516 						(0 != item->itemid ? "update" : "create"), item->key);
1517 
1518 			if (0 != item->itemid)
1519 			{
1520 				lld_field_str_rollback(&item->key, &item->key_orig, &item->flags,
1521 						ZBX_FLAG_LLD_ITEM_UPDATE_KEY);
1522 			}
1523 			else
1524 				item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1525 		}
1526 		else
1527 			zbx_hashset_insert(&items_keys, &item->key, sizeof(char *));
1528 	}
1529 
1530 	zbx_hashset_destroy(&items_keys);
1531 
1532 	/* check preprocessing steps for new and updated discovered items */
1533 	for (i = 0; i < items->values_num; i++)
1534 	{
1535 		item = (zbx_lld_item_t *)items->values[i];
1536 
1537 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1538 			continue;
1539 
1540 		for (j = 0; j < item->preproc_ops.values_num; j++)
1541 		{
1542 			if (SUCCEED != lld_items_preproc_step_validate(item->preproc_ops.values[j], item->itemid,
1543 					error))
1544 			{
1545 				item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1546 				break;
1547 			}
1548 		}
1549 	}
1550 
1551 
1552 	/* check duplicated keys in DB */
1553 	for (i = 0; i < items->values_num; i++)
1554 	{
1555 		item = (zbx_lld_item_t *)items->values[i];
1556 
1557 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1558 			continue;
1559 
1560 		if (0 != item->itemid)
1561 			zbx_vector_uint64_append(&itemids, item->itemid);
1562 
1563 		if (0 != item->itemid && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
1564 			continue;
1565 
1566 		zbx_vector_str_append(&keys, item->key);
1567 	}
1568 
1569 	if (0 != keys.values_num)
1570 	{
1571 		char	*sql = NULL;
1572 		size_t	sql_alloc = 256, sql_offset = 0;
1573 
1574 		sql = (char *)zbx_malloc(sql, sql_alloc);
1575 
1576 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1577 				"select key_"
1578 				" from items"
1579 				" where hostid=" ZBX_FS_UI64
1580 					" and",
1581 				hostid);
1582 		DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "key_",
1583 				(const char **)keys.values, keys.values_num);
1584 
1585 		if (0 != itemids.values_num)
1586 		{
1587 			zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1588 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
1589 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
1590 					itemids.values, itemids.values_num);
1591 		}
1592 
1593 		result = DBselect("%s", sql);
1594 
1595 		while (NULL != (row = DBfetch(result)))
1596 		{
1597 			for (i = 0; i < items->values_num; i++)
1598 			{
1599 				item = (zbx_lld_item_t *)items->values[i];
1600 
1601 				if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1602 					continue;
1603 
1604 				if (0 == strcmp(item->key, row[0]))
1605 				{
1606 					*error = zbx_strdcatf(*error, "Cannot %s item:"
1607 							" item with the same key \"%s\" already exists.\n",
1608 							(0 != item->itemid ? "update" : "create"), item->key);
1609 
1610 					if (0 != item->itemid)
1611 					{
1612 						lld_field_str_rollback(&item->key, &item->key_orig, &item->flags,
1613 								ZBX_FLAG_LLD_ITEM_UPDATE_KEY);
1614 					}
1615 					else
1616 						item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1617 
1618 					continue;
1619 				}
1620 			}
1621 		}
1622 		DBfree_result(result);
1623 
1624 		zbx_free(sql);
1625 	}
1626 
1627 	zbx_vector_str_destroy(&keys);
1628 	zbx_vector_uint64_destroy(&itemids);
1629 
1630 	/* check limit of dependent items in the dependency tree */
1631 	if (0 != item_dependencies->values_num)
1632 	{
1633 		for (i = 0; i < items->values_num; i++)
1634 		{
1635 			int				index;
1636 			const zbx_lld_item_prototype_t	*item_prototype;
1637 
1638 			item = (zbx_lld_item_t *)items->values[i];
1639 
1640 			if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED) || 0 == item->master_itemid
1641 					|| (0 != item->itemid && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TYPE)))
1642 			{
1643 				continue;
1644 			}
1645 
1646 			if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
1647 					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1648 			{
1649 				THIS_SHOULD_NEVER_HAPPEN;
1650 				continue;
1651 			}
1652 
1653 			item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
1654 
1655 			if (SUCCEED != lld_item_dependencies_check(item, item_prototype, item_dependencies))
1656 			{
1657 				*error = zbx_strdcatf(*error,
1658 						"Cannot create item \"%s\": maximum dependent item count reached.\n",
1659 						item->key);
1660 
1661 				item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1662 			}
1663 		}
1664 	}
1665 
1666 	/* check for broken dependent items */
1667 	for (i = 0; i < items->values_num; i++)
1668 	{
1669 		item = (zbx_lld_item_t *)items->values[i];
1670 
1671 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1672 		{
1673 			for (j = 0; j < item->dependent_items.values_num; j++)
1674 			{
1675 				zbx_lld_item_t	*dependent;
1676 
1677 				dependent = (zbx_lld_item_t *)item->dependent_items.values[j];
1678 				dependent->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1679 			}
1680 		}
1681 	}
1682 
1683 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1684 }
1685 
1686 /******************************************************************************
1687  *                                                                            *
1688  * Function: substitute_formula_macros                                        *
1689  *                                                                            *
1690  * Purpose: substitutes lld macros in calculated item formula expression      *
1691  *                                                                            *
1692  * Parameters: data          - [IN/OUT] the expression                        *
1693  *             jp_row        - [IN] the lld data row                          *
1694  *             error         - [IN] pointer to string for reporting errors    *
1695  *             max_error_len - [IN] size of 'error' string                    *
1696  *                                                                            *
1697  ******************************************************************************/
substitute_formula_macros(char ** data,const struct zbx_json_parse * jp_row,char * error,size_t max_error_len)1698 static int	substitute_formula_macros(char **data, const struct zbx_json_parse *jp_row,
1699 		char *error, size_t max_error_len)
1700 {
1701 	const char	*__function_name = "substitute_formula_macros";
1702 
1703 	char		*exp, *tmp, *e;
1704 	size_t		exp_alloc = 128, exp_offset = 0, tmp_alloc = 128, tmp_offset = 0, f_pos, par_l, par_r;
1705 	int		ret = FAIL;
1706 
1707 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1708 
1709 	exp = (char *)zbx_malloc(NULL, exp_alloc);
1710 	tmp = (char *)zbx_malloc(NULL, tmp_alloc);
1711 
1712 	for (e = *data; SUCCEED == zbx_function_find(e, &f_pos, &par_l, &par_r, error, max_error_len); e += par_r + 1)
1713 	{
1714 		/* substitute LLD macros in the part of the string preceding function parameters */
1715 
1716 		zbx_strncpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e, par_l + 1);
1717 		if (SUCCEED != substitute_lld_macros(&tmp, jp_row, ZBX_MACRO_NUMERIC, error, max_error_len))
1718 			goto out;
1719 
1720 		tmp_offset = strlen(tmp);
1721 		zbx_strncpy_alloc(&exp, &exp_alloc, &exp_offset, tmp, tmp_offset);
1722 
1723 		tmp_alloc = tmp_offset + 1;
1724 		tmp_offset = 0;
1725 
1726 		/* substitute LLD macros in function parameters */
1727 
1728 		if (SUCCEED != substitute_function_lld_param(e + par_l + 1, par_r - (par_l + 1), 1,
1729 				&exp, &exp_alloc, &exp_offset, jp_row, error, max_error_len))
1730 		{
1731 			goto out;
1732 		}
1733 
1734 		zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, ")");
1735 	}
1736 
1737 	if (par_l > par_r)
1738 		goto out;
1739 
1740 	/* substitute LLD macros in the remaining part */
1741 
1742 	zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e);
1743 	if (SUCCEED != substitute_lld_macros(&tmp, jp_row, ZBX_MACRO_NUMERIC, error, max_error_len))
1744 		goto out;
1745 
1746 	zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, tmp);
1747 
1748 	ret = SUCCEED;
1749 out:
1750 	zbx_free(tmp);
1751 
1752 	if (SUCCEED == ret)
1753 	{
1754 		zbx_free(*data);
1755 		*data = exp;
1756 	}
1757 	else
1758 		zbx_free(exp);
1759 
1760 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1761 
1762 	return ret;
1763 }
1764 
1765 /******************************************************************************
1766  *                                                                            *
1767  * Function: lld_item_make                                                    *
1768  *                                                                            *
1769  * Purpose: creates a new item based on item prototype and lld data row       *
1770  *                                                                            *
1771  * Parameters: item_prototype - [IN] the item prototype                       *
1772  *             lld_row        - [IN] the lld row                              *
1773  *                                                                            *
1774  * Returns: The created item or NULL if cannot create new item from prototype *
1775  *                                                                            *
1776  ******************************************************************************/
lld_item_make(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_row_t * lld_row,char ** error)1777 static zbx_lld_item_t	*lld_item_make(const zbx_lld_item_prototype_t *item_prototype, const zbx_lld_row_t *lld_row,
1778 		char **error)
1779 {
1780 	const char			*__function_name = "lld_item_make";
1781 
1782 	zbx_lld_item_t			*item;
1783 	const struct zbx_json_parse	*jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
1784 	char				err[MAX_STRING_LEN];
1785 	int				ret;
1786 
1787 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1788 
1789 	item = (zbx_lld_item_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_t));
1790 
1791 	item->itemid = 0;
1792 	item->parent_itemid = item_prototype->itemid;
1793 	item->lastcheck = 0;
1794 	item->ts_delete = 0;
1795 	item->type = item_prototype->type;
1796 	item->key_proto = NULL;
1797 	item->master_itemid = item_prototype->master_itemid;
1798 
1799 	item->name = zbx_strdup(NULL, item_prototype->name);
1800 	item->name_proto = NULL;
1801 	substitute_lld_macros(&item->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
1802 	zbx_lrtrim(item->name, ZBX_WHITESPACE);
1803 
1804 	item->key = zbx_strdup(NULL, item_prototype->key);
1805 	item->key_orig = NULL;
1806 
1807 	if (FAIL == (ret = substitute_key_macros(&item->key, NULL, NULL, jp_row, MACRO_TYPE_ITEM_KEY, err,
1808 			sizeof(err))))
1809 	{
1810 		*error = zbx_strdcatf(*error, "Cannot create item, error in item key parameters %s.\n", err);
1811 	}
1812 
1813 	item->delay = zbx_strdup(NULL, item_prototype->delay);
1814 	item->delay_orig = NULL;
1815 	substitute_lld_macros(&item->delay, jp_row, ZBX_MACRO_ANY, NULL, 0);
1816 	zbx_lrtrim(item->delay, ZBX_WHITESPACE);
1817 
1818 	item->history = zbx_strdup(NULL, item_prototype->history);
1819 	item->history_orig = NULL;
1820 	substitute_lld_macros(&item->history, jp_row, ZBX_MACRO_ANY, NULL, 0);
1821 	zbx_lrtrim(item->history, ZBX_WHITESPACE);
1822 
1823 	item->trends = zbx_strdup(NULL, item_prototype->trends);
1824 	item->trends_orig = NULL;
1825 	substitute_lld_macros(&item->trends, jp_row, ZBX_MACRO_ANY, NULL, 0);
1826 	zbx_lrtrim(item->trends, ZBX_WHITESPACE);
1827 
1828 	item->units = zbx_strdup(NULL, item_prototype->units);
1829 	item->units_orig = NULL;
1830 	substitute_lld_macros(&item->units, jp_row, ZBX_MACRO_ANY, NULL, 0);
1831 	zbx_lrtrim(item->units, ZBX_WHITESPACE);
1832 
1833 	item->params = zbx_strdup(NULL, item_prototype->params);
1834 	item->params_orig = NULL;
1835 
1836 	if (ITEM_TYPE_CALCULATED == item_prototype->type)
1837 	{
1838 		if (SUCCEED == ret && FAIL == (ret = substitute_formula_macros(&item->params, jp_row, err,
1839 				sizeof(err))))
1840 		{
1841 			*error = zbx_strdcatf(*error, "Cannot create item, error in formula: %s.\n", err);
1842 		}
1843 	}
1844 	else
1845 		substitute_lld_macros(&item->params, jp_row, ZBX_MACRO_ANY, NULL, 0);
1846 
1847 	zbx_lrtrim(item->params, ZBX_WHITESPACE);
1848 
1849 	item->ipmi_sensor = zbx_strdup(NULL, item_prototype->ipmi_sensor);
1850 	item->ipmi_sensor_orig = NULL;
1851 	substitute_lld_macros(&item->ipmi_sensor, jp_row, ZBX_MACRO_ANY, NULL, 0);
1852 	/* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1853 
1854 	item->snmp_oid = zbx_strdup(NULL, item_prototype->snmp_oid);
1855 	item->snmp_oid_orig = NULL;
1856 
1857 	if (SUCCEED == ret && (ITEM_TYPE_SNMPv1 == item_prototype->type || ITEM_TYPE_SNMPv2c == item_prototype->type ||
1858 			ITEM_TYPE_SNMPv3 == item_prototype->type) &&
1859 			FAIL == (ret = substitute_key_macros(&item->snmp_oid, NULL, NULL, jp_row, MACRO_TYPE_SNMP_OID,
1860 			err, sizeof(err))))
1861 	{
1862 		*error = zbx_strdcatf(*error, "Cannot create item, error in SNMP OID key parameters: %s.\n", err);
1863 	}
1864 
1865 	zbx_lrtrim(item->snmp_oid, ZBX_WHITESPACE);
1866 
1867 	item->username = zbx_strdup(NULL, item_prototype->username);
1868 	item->username_orig = NULL;
1869 	substitute_lld_macros(&item->username, jp_row, ZBX_MACRO_ANY, NULL, 0);
1870 	/* zbx_lrtrim(item->username, ZBX_WHITESPACE); is not missing here */
1871 
1872 	item->password = zbx_strdup(NULL, item_prototype->password);
1873 	item->password_orig = NULL;
1874 	substitute_lld_macros(&item->password, jp_row, ZBX_MACRO_ANY, NULL, 0);
1875 	/* zbx_lrtrim(item->password, ZBX_WHITESPACE); is not missing here */
1876 
1877 	item->description = zbx_strdup(NULL, item_prototype->description);
1878 	item->description_orig = NULL;
1879 	substitute_lld_macros(&item->description, jp_row, ZBX_MACRO_ANY, NULL, 0);
1880 	zbx_lrtrim(item->description, ZBX_WHITESPACE);
1881 
1882 	item->jmx_endpoint = zbx_strdup(NULL, item_prototype->jmx_endpoint);
1883 	item->jmx_endpoint_orig = NULL;
1884 	substitute_lld_macros(&item->jmx_endpoint, jp_row, ZBX_MACRO_ANY, NULL, 0);
1885 	/* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1886 
1887 	item->timeout = zbx_strdup(NULL, item_prototype->timeout);
1888 	item->timeout_orig = NULL;
1889 	substitute_lld_macros(&item->timeout, jp_row, ZBX_MACRO_ANY, NULL, 0);
1890 	zbx_lrtrim(item->timeout, ZBX_WHITESPACE);
1891 
1892 	item->url = zbx_strdup(NULL, item_prototype->url);
1893 	item->url_orig = NULL;
1894 	substitute_lld_macros(&item->url, jp_row, ZBX_MACRO_ANY, NULL, 0);
1895 	zbx_lrtrim(item->url, ZBX_WHITESPACE);
1896 
1897 	item->query_fields = zbx_strdup(NULL, item_prototype->query_fields);
1898 	item->query_fields_orig = NULL;
1899 
1900 	if (SUCCEED == ret && FAIL == (ret = substitute_macros_in_json_pairs(&item->query_fields, jp_row, err,
1901 			sizeof(err))))
1902 	{
1903 		*error = zbx_strdcatf(*error, "Cannot create item, error in JSON: %s.\n", err);
1904 	}
1905 
1906 	item->posts = zbx_strdup(NULL, item_prototype->posts);
1907 	item->posts_orig = NULL;
1908 
1909 	switch (item_prototype->post_type)
1910 	{
1911 		case ZBX_POSTTYPE_JSON:
1912 			substitute_lld_macros(&item->posts, jp_row, ZBX_MACRO_JSON, NULL, 0);
1913 			break;
1914 		case ZBX_POSTTYPE_XML:
1915 			if (SUCCEED == ret && FAIL == (ret = substitute_macros_xml(&item->posts, NULL, jp_row, err,
1916 					sizeof(err))))
1917 			{
1918 				zbx_lrtrim(err, ZBX_WHITESPACE);
1919 				*error = zbx_strdcatf(*error, "Cannot create item, error in XML: %s.\n", err);
1920 			}
1921 			break;
1922 		default:
1923 			substitute_lld_macros(&item->posts, jp_row, ZBX_MACRO_ANY, NULL, 0);
1924 			/* zbx_lrtrim(item->posts, ZBX_WHITESPACE); is not missing here */
1925 			break;
1926 	}
1927 
1928 	item->status_codes = zbx_strdup(NULL, item_prototype->status_codes);
1929 	item->status_codes_orig = NULL;
1930 	substitute_lld_macros(&item->status_codes, jp_row, ZBX_MACRO_ANY, NULL, 0);
1931 	zbx_lrtrim(item->status_codes, ZBX_WHITESPACE);
1932 
1933 	item->http_proxy = zbx_strdup(NULL, item_prototype->http_proxy);
1934 	item->http_proxy_orig = NULL;
1935 	substitute_lld_macros(&item->http_proxy, jp_row, ZBX_MACRO_ANY, NULL, 0);
1936 	zbx_lrtrim(item->http_proxy, ZBX_WHITESPACE);
1937 
1938 	item->headers = zbx_strdup(NULL, item_prototype->headers);
1939 	item->headers_orig = NULL;
1940 	substitute_lld_macros(&item->headers, jp_row, ZBX_MACRO_ANY, NULL, 0);
1941 	/* zbx_lrtrim(item->headers, ZBX_WHITESPACE); is not missing here */
1942 
1943 	item->ssl_cert_file = zbx_strdup(NULL, item_prototype->ssl_cert_file);
1944 	item->ssl_cert_file_orig = NULL;
1945 	substitute_lld_macros(&item->ssl_cert_file, jp_row, ZBX_MACRO_ANY, NULL, 0);
1946 	/* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1947 
1948 	item->ssl_key_file = zbx_strdup(NULL, item_prototype->ssl_key_file);
1949 	item->ssl_key_file_orig = NULL;
1950 	substitute_lld_macros(&item->ssl_key_file, jp_row, ZBX_MACRO_ANY, NULL, 0);
1951 	/* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1952 
1953 	item->ssl_key_password = zbx_strdup(NULL, item_prototype->ssl_key_password);
1954 	item->ssl_key_password_orig = NULL;
1955 	substitute_lld_macros(&item->ssl_key_password, jp_row, ZBX_MACRO_ANY, NULL, 0);
1956 	/* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1957 
1958 	item->flags = ZBX_FLAG_LLD_ITEM_DISCOVERED;
1959 	item->lld_row = lld_row;
1960 
1961 	zbx_vector_ptr_create(&item->preproc_ops);
1962 	zbx_vector_ptr_create(&item->dependent_items);
1963 
1964 	if (SUCCEED != ret)
1965 	{
1966 		lld_item_free(item);
1967 		item = NULL;
1968 	}
1969 
1970 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1971 
1972 	return item;
1973 }
1974 
1975 /******************************************************************************
1976  *                                                                            *
1977  * Function: lld_item_update                                                  *
1978  *                                                                            *
1979  * Purpose: updates an existing item based on item prototype and lld data row *
1980  *                                                                            *
1981  * Parameters: item_prototype - [IN] the item prototype                       *
1982  *             lld_row        - [IN] the lld row                              *
1983  *             item           - [IN] an existing item or NULL                 *
1984  *                                                                            *
1985  ******************************************************************************/
lld_item_update(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_row_t * lld_row,zbx_lld_item_t * item,char ** error)1986 static void	lld_item_update(const zbx_lld_item_prototype_t *item_prototype, const zbx_lld_row_t *lld_row,
1987 		zbx_lld_item_t *item, char **error)
1988 {
1989 	const char		*__function_name = "lld_item_update";
1990 
1991 	char			*buffer = NULL, err[MAX_STRING_LEN];
1992 	struct zbx_json_parse	*jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
1993 
1994 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1995 
1996 	buffer = zbx_strdup(buffer, item_prototype->name);
1997 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
1998 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
1999 	if (0 != strcmp(item->name, buffer))
2000 	{
2001 		item->name_proto = item->name;
2002 		item->name = buffer;
2003 		buffer = NULL;
2004 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_NAME;
2005 	}
2006 
2007 	if (0 != strcmp(item->key_proto, item_prototype->key))
2008 	{
2009 		buffer = zbx_strdup(buffer, item_prototype->key);
2010 
2011 		if (SUCCEED == substitute_key_macros(&buffer, NULL, NULL, jp_row, MACRO_TYPE_ITEM_KEY, err,
2012 				sizeof(err)))
2013 		{
2014 			item->key_orig = item->key;
2015 			item->key = buffer;
2016 			buffer = NULL;
2017 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_KEY;
2018 		}
2019 		else
2020 			*error = zbx_strdcatf(*error, "Cannot update item, error in item key parameters: %s.\n", err);
2021 	}
2022 
2023 	buffer = zbx_strdup(buffer, item_prototype->delay);
2024 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2025 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2026 	if (0 != strcmp(item->delay, buffer))
2027 	{
2028 		item->delay_orig = item->delay;
2029 		item->delay = buffer;
2030 		buffer = NULL;
2031 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DELAY;
2032 	}
2033 
2034 	buffer = zbx_strdup(buffer, item_prototype->history);
2035 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2036 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2037 	if (0 != strcmp(item->history, buffer))
2038 	{
2039 		item->history_orig = item->history;
2040 		item->history = buffer;
2041 		buffer = NULL;
2042 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY;
2043 	}
2044 
2045 	buffer = zbx_strdup(buffer, item_prototype->trends);
2046 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2047 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2048 	if (0 != strcmp(item->trends, buffer))
2049 	{
2050 		item->trends_orig = item->trends;
2051 		item->trends = buffer;
2052 		buffer = NULL;
2053 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS;
2054 	}
2055 
2056 	buffer = zbx_strdup(buffer, item_prototype->units);
2057 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2058 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2059 	if (0 != strcmp(item->units, buffer))
2060 	{
2061 		item->units_orig = item->units;
2062 		item->units = buffer;
2063 		buffer = NULL;
2064 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_UNITS;
2065 	}
2066 
2067 	buffer = zbx_strdup(buffer, item_prototype->params);
2068 
2069 	if (ITEM_TYPE_CALCULATED == item_prototype->type)
2070 	{
2071 		if (SUCCEED == substitute_formula_macros(&buffer, jp_row, err, sizeof(err)))
2072 		{
2073 			zbx_lrtrim(buffer, ZBX_WHITESPACE);
2074 
2075 			if (0 != strcmp(item->params, buffer))
2076 			{
2077 				item->params_orig = item->params;
2078 				item->params = buffer;
2079 				buffer = NULL;
2080 				item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS;
2081 			}
2082 		}
2083 		else
2084 			*error = zbx_strdcatf(*error, "Cannot update item, error in formula: %s.\n", err);
2085 	}
2086 	else
2087 	{
2088 		substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2089 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
2090 
2091 		if (0 != strcmp(item->params, buffer))
2092 		{
2093 			item->params_orig = item->params;
2094 			item->params = buffer;
2095 			buffer = NULL;
2096 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS;
2097 		}
2098 	}
2099 
2100 	buffer = zbx_strdup(buffer, item_prototype->ipmi_sensor);
2101 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2102 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2103 	if (0 != strcmp(item->ipmi_sensor, buffer))
2104 	{
2105 		item->ipmi_sensor_orig = item->ipmi_sensor;
2106 		item->ipmi_sensor = buffer;
2107 		buffer = NULL;
2108 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR;
2109 	}
2110 
2111 	buffer = zbx_strdup(buffer, item_prototype->snmp_oid);
2112 
2113 	if ((ITEM_TYPE_SNMPv1 == item_prototype->type || ITEM_TYPE_SNMPv2c == item_prototype->type ||
2114 			ITEM_TYPE_SNMPv3 == item_prototype->type) &&
2115 			FAIL == substitute_key_macros(&buffer, NULL, NULL, jp_row, MACRO_TYPE_SNMP_OID, err,
2116 			sizeof(err)))
2117 	{
2118 		*error = zbx_strdcatf(*error, "Cannot update item, error in SNMP OID key parameters: %s.\n", err);
2119 	}
2120 
2121 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2122 	if (0 != strcmp(item->snmp_oid, buffer))
2123 	{
2124 		item->snmp_oid_orig = item->snmp_oid;
2125 		item->snmp_oid = buffer;
2126 		buffer = NULL;
2127 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID;
2128 	}
2129 
2130 	buffer = zbx_strdup(buffer, item_prototype->username);
2131 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2132 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2133 	if (0 != strcmp(item->username, buffer))
2134 	{
2135 		item->username_orig = item->username;
2136 		item->username = buffer;
2137 		buffer = NULL;
2138 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME;
2139 	}
2140 
2141 	buffer = zbx_strdup(buffer, item_prototype->password);
2142 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2143 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2144 	if (0 != strcmp(item->password, buffer))
2145 	{
2146 		item->password_orig = item->password;
2147 		item->password = buffer;
2148 		buffer = NULL;
2149 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD;
2150 	}
2151 
2152 	buffer = zbx_strdup(buffer, item_prototype->description);
2153 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2154 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2155 	if (0 != strcmp(item->description, buffer))
2156 	{
2157 		item->description_orig = item->description;
2158 		item->description = buffer;
2159 		buffer = NULL;
2160 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION;
2161 	}
2162 
2163 	buffer = zbx_strdup(buffer, item_prototype->jmx_endpoint);
2164 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2165 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2166 	if (0 != strcmp(item->jmx_endpoint, buffer))
2167 	{
2168 		item->jmx_endpoint_orig = item->jmx_endpoint;
2169 		item->jmx_endpoint = buffer;
2170 		buffer = NULL;
2171 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_JMX_ENDPOINT;
2172 	}
2173 
2174 	buffer = zbx_strdup(buffer, item_prototype->timeout);
2175 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2176 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2177 	if (0 != strcmp(item->timeout, buffer))
2178 	{
2179 		item->timeout_orig = item->timeout;
2180 		item->timeout = buffer;
2181 		buffer = NULL;
2182 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TIMEOUT;
2183 	}
2184 
2185 	buffer = zbx_strdup(buffer, item_prototype->url);
2186 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2187 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2188 	if (0 != strcmp(item->url, buffer))
2189 	{
2190 		item->url_orig = item->url;
2191 		item->url = buffer;
2192 		buffer = NULL;
2193 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_URL;
2194 	}
2195 
2196 	buffer = zbx_strdup(buffer, item_prototype->query_fields);
2197 
2198 	if (FAIL == substitute_macros_in_json_pairs(&buffer, jp_row, err, sizeof(err)))
2199 		*error = zbx_strdcatf(*error, "Cannot update item, error in JSON: %s.\n", err);
2200 
2201 	if (0 != strcmp(item->query_fields, buffer))
2202 	{
2203 		item->query_fields_orig = item->query_fields;
2204 		item->query_fields = buffer;
2205 		buffer = NULL;
2206 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_QUERY_FIELDS;
2207 	}
2208 
2209 	buffer = zbx_strdup(buffer, item_prototype->posts);
2210 
2211 	if (ZBX_POSTTYPE_JSON == item_prototype->post_type)
2212 	{
2213 		substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_JSON, NULL, 0);
2214 	}
2215 	else if (ZBX_POSTTYPE_XML == item_prototype->post_type)
2216 	{
2217 		if (FAIL == substitute_macros_xml(&buffer, NULL, jp_row, err, sizeof(err)))
2218 		{
2219 			zbx_lrtrim(err, ZBX_WHITESPACE);
2220 			*error = zbx_strdcatf(*error, "Cannot update item, error in XML: %s.\n", err);
2221 		}
2222 	}
2223 	else
2224 		substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2225 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2226 	if (0 != strcmp(item->posts, buffer))
2227 	{
2228 		item->posts_orig = item->posts;
2229 		item->posts = buffer;
2230 		buffer = NULL;
2231 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_POSTS;
2232 	}
2233 
2234 	buffer = zbx_strdup(buffer, item_prototype->status_codes);
2235 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2236 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2237 	if (0 != strcmp(item->status_codes, buffer))
2238 	{
2239 		item->status_codes_orig = item->status_codes;
2240 		item->status_codes = buffer;
2241 		buffer = NULL;
2242 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_STATUS_CODES;
2243 	}
2244 
2245 	buffer = zbx_strdup(buffer, item_prototype->http_proxy);
2246 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2247 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
2248 	if (0 != strcmp(item->http_proxy, buffer))
2249 	{
2250 		item->http_proxy_orig = item->http_proxy;
2251 		item->http_proxy = buffer;
2252 		buffer = NULL;
2253 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_HTTP_PROXY;
2254 	}
2255 
2256 	buffer = zbx_strdup(buffer, item_prototype->headers);
2257 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2258 	/*zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2259 	if (0 != strcmp(item->headers, buffer))
2260 	{
2261 		item->headers_orig = item->headers;
2262 		item->headers = buffer;
2263 		buffer = NULL;
2264 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_HEADERS;
2265 	}
2266 
2267 	buffer = zbx_strdup(buffer, item_prototype->ssl_cert_file);
2268 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2269 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2270 	if (0 != strcmp(item->ssl_cert_file, buffer))
2271 	{
2272 		item->ssl_cert_file_orig = item->ssl_cert_file;
2273 		item->ssl_cert_file = buffer;
2274 		buffer = NULL;
2275 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SSL_CERT_FILE;
2276 	}
2277 
2278 	buffer = zbx_strdup(buffer, item_prototype->ssl_key_file);
2279 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2280 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2281 	if (0 != strcmp(item->ssl_key_file, buffer))
2282 	{
2283 		item->ssl_key_file_orig = item->ssl_key_file;
2284 		item->ssl_key_file = buffer;
2285 		buffer = NULL;
2286 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_FILE;
2287 	}
2288 
2289 	buffer = zbx_strdup(buffer, item_prototype->ssl_key_password);
2290 	substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2291 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2292 	if (0 != strcmp(item->ssl_key_password, buffer))
2293 	{
2294 		item->ssl_key_password_orig = item->ssl_key_password;
2295 		item->ssl_key_password = buffer;
2296 		buffer = NULL;
2297 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_PASSWORD;
2298 	}
2299 
2300 	item->flags |= ZBX_FLAG_LLD_ITEM_DISCOVERED;
2301 	item->lld_row = lld_row;
2302 
2303 	zbx_free(buffer);
2304 
2305 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2306 }
2307 
2308 /******************************************************************************
2309  *                                                                            *
2310  * Function: lld_items_make                                                   *
2311  *                                                                            *
2312  * Purpose: updates existing items and creates new ones based on item         *
2313  *          item prototypes and lld data                                      *
2314  *                                                                            *
2315  * Parameters: item_prototypes - [IN] the item prototypes                     *
2316  *             lld_rows        - [IN] the lld data rows                       *
2317  *             items           - [IN/OUT] sorted list of items                *
2318  *             items_index     - [OUT] index of items based on prototype ids  *
2319  *                                     and lld rows. Used to quckly find an   *
2320  *                                     item by prototype and lld_row.         *
2321  *             error           - [IN/OUT] the lld error message               *
2322  *                                                                            *
2323  ******************************************************************************/
lld_items_make(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * lld_rows,zbx_vector_ptr_t * items,zbx_hashset_t * items_index,char ** error)2324 static void	lld_items_make(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *lld_rows,
2325 		zbx_vector_ptr_t *items, zbx_hashset_t *items_index, char **error)
2326 {
2327 	const char			*__function_name = "lld_items_make";
2328 	int				i, j, index;
2329 	zbx_lld_item_prototype_t	*item_prototype;
2330 	zbx_lld_item_t			*item;
2331 	zbx_lld_row_t			*lld_row;
2332 	zbx_lld_item_index_t		*item_index, item_index_local;
2333 	char				*buffer = NULL;
2334 
2335 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2336 
2337 	/* create the items index */
2338 	for (i = 0; i < item_prototypes->values_num; i++)
2339 	{
2340 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
2341 
2342 		for (j = 0; j < lld_rows->values_num; j++)
2343 			zbx_vector_ptr_append(&item_prototype->lld_rows, lld_rows->values[j]);
2344 	}
2345 
2346 	/* Iterate in reverse order because usually the items are created in the same order as     */
2347 	/* incoming lld rows. Iterating in reverse optimizes lld_row removal from item prototypes. */
2348 	for (i = items->values_num - 1; i >= 0; i--)
2349 	{
2350 		item = (zbx_lld_item_t *)items->values[i];
2351 
2352 		if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
2353 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2354 		{
2355 			THIS_SHOULD_NEVER_HAPPEN;
2356 			continue;
2357 		}
2358 
2359 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
2360 
2361 		for (j = item_prototype->lld_rows.values_num - 1; j >= 0; j--)
2362 		{
2363 			lld_row = (zbx_lld_row_t *)item_prototype->lld_rows.values[j];
2364 
2365 			buffer = zbx_strdup(buffer, item->key_proto);
2366 
2367 			if (SUCCEED != substitute_key_macros(&buffer, NULL, NULL, &lld_row->jp_row, MACRO_TYPE_ITEM_KEY,
2368 					NULL, 0))
2369 			{
2370 				continue;
2371 			}
2372 
2373 			if (0 == strcmp(item->key, buffer))
2374 			{
2375 				item_index_local.parent_itemid = item->parent_itemid;
2376 				item_index_local.lld_row = lld_row;
2377 				item_index_local.item = item;
2378 				zbx_hashset_insert(items_index, &item_index_local, sizeof(item_index_local));
2379 
2380 				zbx_vector_ptr_remove_noorder(&item_prototype->lld_rows, j);
2381 				break;
2382 			}
2383 		}
2384 	}
2385 
2386 	zbx_free(buffer);
2387 
2388 	/* update/create discovered items */
2389 	for (i = 0; i < item_prototypes->values_num; i++)
2390 	{
2391 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
2392 		item_index_local.parent_itemid = item_prototype->itemid;
2393 
2394 		for (j = 0; j < lld_rows->values_num; j++)
2395 		{
2396 			item_index_local.lld_row = (zbx_lld_row_t *)lld_rows->values[j];
2397 
2398 			if (NULL == (item_index = (zbx_lld_item_index_t *)zbx_hashset_search(items_index, &item_index_local)))
2399 			{
2400 				if (NULL != (item = lld_item_make(item_prototype, item_index_local.lld_row, error)))
2401 				{
2402 					/* add the created item to items vector and update index */
2403 					zbx_vector_ptr_append(items, item);
2404 					item_index_local.item = item;
2405 					zbx_hashset_insert(items_index, &item_index_local, sizeof(item_index_local));
2406 				}
2407 			}
2408 			else
2409 				lld_item_update(item_prototype, item_index_local.lld_row, item_index->item, error);
2410 		}
2411 	}
2412 
2413 	zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2414 
2415 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d items", __function_name, items->values_num);
2416 }
2417 
2418 /******************************************************************************
2419  *                                                                            *
2420  * Function: lld_items_preproc_susbstitute_params_macros                      *
2421  *                                                                            *
2422  * Purpose: escaping of a symbols in items preprocessing steps for discovery  *
2423  *          process                                                           *
2424  *                                                                            *
2425  * Parameters: pp         - [IN] the item preprocessing step                  *
2426  *             lld_row    - [IN] lld source value                             *
2427  *             itemid     - [IN] item ID for logging                          *
2428  *             sub_params - [IN/OUT] the pp params value after substitute     *
2429  *             error      - [IN/OUT] the lld error message                    *
2430  *                                                                            *
2431  * Return value: SUCCEED - if preprocessing steps are valid                   *
2432  *               FAIL    - if substitute_lld_macros fails                     *
2433  *                                                                            *
2434  ******************************************************************************/
lld_items_preproc_susbstitute_params_macros(const zbx_lld_item_preproc_t * pp,const zbx_lld_row_t * lld_row,zbx_uint64_t itemid,char ** sub_params,char ** error)2435 static int	lld_items_preproc_susbstitute_params_macros(const zbx_lld_item_preproc_t * pp,
2436 		const zbx_lld_row_t * lld_row, zbx_uint64_t itemid, char **sub_params, char **error)
2437 {
2438 	int	flags1, flags2, params_num = 1;
2439 
2440 	switch(pp->type)
2441 	{
2442 		case ZBX_PREPROC_REGSUB:
2443 			flags1 = ZBX_MACRO_ANY | ZBX_TOKEN_REGEXP;
2444 			flags2 = ZBX_MACRO_ANY | ZBX_TOKEN_REGEXP_OUTPUT;
2445 			params_num = 2;
2446 			break;
2447 		case ZBX_PREPROC_XPATH:
2448 			flags1 = ZBX_MACRO_ANY | ZBX_TOKEN_XPATH;
2449 			break;
2450 		case ZBX_PREPROC_JSONPATH:
2451 			flags1 = ZBX_MACRO_ANY | ZBX_TOKEN_JSONPATH;
2452 			break;
2453 		default:
2454 			flags1 = ZBX_MACRO_ANY;
2455 	}
2456 
2457 	if (2 == params_num)
2458 	{
2459 		char	*param1 = NULL, *param2 = NULL;
2460 		size_t	sub_params_size;
2461 
2462 		zbx_strsplit(pp->params, '\n', &param1, &param2);
2463 
2464 		if (NULL == param2)
2465 		{
2466 			zbx_free(param1);
2467 			*error = zbx_strdcatf(*error, "Cannot %s item: invalid preprocessing step #%d parameters: %s.\n",
2468 					(0 != itemid ? "update" : "create"), pp->step, pp->params);
2469 			return FAIL;
2470 		}
2471 
2472 		substitute_lld_macros(&param1, &lld_row->jp_row, flags1, NULL, 0);
2473 		substitute_lld_macros(&param2, &lld_row->jp_row, flags2, NULL, 0);
2474 
2475 		sub_params_size = strlen(param1) + strlen(param2) + 2;
2476 		*sub_params = zbx_malloc(NULL, sub_params_size);
2477 
2478 		zbx_snprintf(*sub_params, sub_params_size, "%s\n%s", param1, param2);
2479 
2480 		zbx_free(param1);
2481 		zbx_free(param2);
2482 	}
2483 	else
2484 	{
2485 		*sub_params = zbx_strdup(NULL, pp->params);
2486 		substitute_lld_macros(sub_params, &lld_row->jp_row, flags1, NULL, 0);
2487 	}
2488 
2489 	return SUCCEED;
2490 }
2491 
2492 /******************************************************************************
2493  *                                                                            *
2494  * Function: lld_items_preproc_make                                           *
2495  *                                                                            *
2496  * Purpose: updates existing items preprocessing operations and create new    *
2497  *          based on item item prototypes                                     *
2498  *                                                                            *
2499  * Parameters: item_prototypes - [IN] the item prototypes                     *
2500  *             items           - [IN/OUT] sorted list of items                *
2501  *             error           - [IN/OUT] the lld error message               *
2502  *                                                                            *
2503  ******************************************************************************/
lld_items_preproc_make(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * items,char ** error)2504 static void	lld_items_preproc_make(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *items, char **error)
2505 {
2506 	int				i, j, index, preproc_num;
2507 	zbx_lld_item_t			*item;
2508 	zbx_lld_item_prototype_t	*item_proto;
2509 	zbx_lld_item_preproc_t		*ppsrc, *ppdst;
2510 	char				*sub_params;
2511 
2512 	for (i = 0; i < items->values_num; i++)
2513 	{
2514 		item = (zbx_lld_item_t *)items->values[i];
2515 
2516 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
2517 			continue;
2518 
2519 		if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
2520 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2521 		{
2522 			THIS_SHOULD_NEVER_HAPPEN;
2523 			continue;
2524 		}
2525 
2526 		zbx_vector_ptr_sort(&item->preproc_ops, lld_item_preproc_sort_by_step);
2527 
2528 		item_proto = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
2529 
2530 		preproc_num = MAX(item->preproc_ops.values_num, item_proto->preproc_ops.values_num);
2531 
2532 		for (j = 0; j < preproc_num; j++)
2533 		{
2534 			if (j >= item->preproc_ops.values_num)
2535 			{
2536 				ppsrc = (zbx_lld_item_preproc_t *)item_proto->preproc_ops.values[j];
2537 				ppdst = (zbx_lld_item_preproc_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_preproc_t));
2538 				ppdst->item_preprocid = 0;
2539 				ppdst->flags = ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED | ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE;
2540 				ppdst->step = ppsrc->step;
2541 				ppdst->type = ppsrc->type;
2542 
2543 				if (SUCCEED != lld_items_preproc_susbstitute_params_macros(ppsrc, item->lld_row,
2544 						item->itemid, &sub_params, error))
2545 				{
2546 					zbx_free(ppdst);
2547 					item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
2548 					break;
2549 				}
2550 
2551 				ppdst->params = sub_params;
2552 				zbx_vector_ptr_append(&item->preproc_ops, ppdst);
2553 				continue;
2554 			}
2555 
2556 			ppdst = (zbx_lld_item_preproc_t *)item->preproc_ops.values[j];
2557 
2558 			if (j >= item_proto->preproc_ops.values_num)
2559 			{
2560 				ppdst->flags &= ~ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED;
2561 				continue;
2562 			}
2563 
2564 			ppsrc = (zbx_lld_item_preproc_t *)item_proto->preproc_ops.values[j];
2565 
2566 			ppdst->flags |= ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED;
2567 
2568 			if (ppdst->type != ppsrc->type)
2569 			{
2570 				ppdst->type = ppsrc->type;
2571 				ppdst->flags |= ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_TYPE;
2572 			}
2573 
2574 			if (ppdst->step != ppsrc->step)
2575 			{
2576 				/* this should never happen */
2577 				ppdst->step = ppsrc->step;
2578 				ppdst->flags |= ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_STEP;
2579 			}
2580 
2581 			if (SUCCEED != lld_items_preproc_susbstitute_params_macros(ppsrc, item->lld_row, item->itemid,
2582 					&sub_params, error))
2583 			{
2584 				item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
2585 				break;
2586 			}
2587 
2588 			if (0 != strcmp(ppdst->params, sub_params))
2589 			{
2590 				zbx_free(ppdst->params);
2591 				ppdst->params = sub_params;
2592 				ppdst->flags |= ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_PARAMS;
2593 			}
2594 			else
2595 				zbx_free(sub_params);
2596 		}
2597 	}
2598 }
2599 
2600 /******************************************************************************
2601  *                                                                            *
2602  * Function: lld_item_save                                                    *
2603  *                                                                            *
2604  * Purpose: recursively prepare LLD item bulk insert if any and               *
2605  *          update dependent items with their masters                         *
2606  *                                                                            *
2607  * Parameters: hostid               - [IN] parent host id                     *
2608  *             item_prototypes      - [IN] item prototypes                    *
2609  *             item                 - [IN/OUT] item to be saved and set       *
2610  *                                             master for dependentent items  *
2611  *             itemid               - [IN/OUT] item id used for insert        *
2612  *                                             operations                     *
2613  *             itemdiscoveryid      - [IN/OUT] item discovery id used for     *
2614  *                                             insert operations              *
2615  *             db_insert            - [IN] prepared item bulk insert          *
2616  *             db_insert_idiscovery - [IN] prepared item discovery bulk       *
2617  *                                         insert                             *
2618  *                                                                            *
2619  ******************************************************************************/
lld_item_save(zbx_uint64_t hostid,const zbx_vector_ptr_t * item_prototypes,zbx_lld_item_t * item,zbx_uint64_t * itemid,zbx_uint64_t * itemdiscoveryid,zbx_db_insert_t * db_insert,zbx_db_insert_t * db_insert_idiscovery)2620 static void	lld_item_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *item_prototypes, zbx_lld_item_t *item,
2621 		zbx_uint64_t *itemid, zbx_uint64_t *itemdiscoveryid, zbx_db_insert_t *db_insert,
2622 		zbx_db_insert_t *db_insert_idiscovery)
2623 {
2624 	int	index;
2625 
2626 	if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
2627 		return;
2628 
2629 	if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
2630 			ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2631 	{
2632 		THIS_SHOULD_NEVER_HAPPEN;
2633 		return;
2634 	}
2635 
2636 	if (0 == item->itemid)
2637 	{
2638 		const zbx_lld_item_prototype_t	*item_prototype;
2639 
2640 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
2641 		item->itemid = (*itemid)++;
2642 
2643 		zbx_db_insert_add_values(db_insert, item->itemid, item->name, item->key, hostid,
2644 				(int)item_prototype->type, (int)item_prototype->value_type,
2645 				item->delay, item->history, item->trends,
2646 				(int)item_prototype->status, item_prototype->trapper_hosts, item->units,
2647 				item_prototype->formula, item_prototype->logtimefmt, item_prototype->valuemapid,
2648 				item->params, item->ipmi_sensor, item_prototype->snmp_community, item->snmp_oid,
2649 				item_prototype->port, item_prototype->snmpv3_securityname,
2650 				(int)item_prototype->snmpv3_securitylevel,
2651 				(int)item_prototype->snmpv3_authprotocol, item_prototype->snmpv3_authpassphrase,
2652 				(int)item_prototype->snmpv3_privprotocol, item_prototype->snmpv3_privpassphrase,
2653 				(int)item_prototype->authtype, item->username,
2654 				item->password, item_prototype->publickey, item_prototype->privatekey,
2655 				item->description, item_prototype->interfaceid, (int)ZBX_FLAG_DISCOVERY_CREATED,
2656 				item_prototype->snmpv3_contextname, item->jmx_endpoint, item->master_itemid,
2657 				item->timeout, item->url, item->query_fields, item->posts, item->status_codes,
2658 				item_prototype->follow_redirects, item_prototype->post_type, item->http_proxy,
2659 				item->headers, item_prototype->retrieve_mode, item_prototype->request_method,
2660 				item_prototype->output_format, item->ssl_cert_file, item->ssl_key_file,
2661 				item->ssl_key_password, item_prototype->verify_peer, item_prototype->verify_host,
2662 				item_prototype->allow_traps);
2663 
2664 		zbx_db_insert_add_values(db_insert_idiscovery, (*itemdiscoveryid)++, item->itemid,
2665 				item->parent_itemid, item_prototype->key);
2666 	}
2667 
2668 	for (index = 0; index < item->dependent_items.values_num; index++)
2669 	{
2670 		zbx_lld_item_t	*dependent;
2671 
2672 		dependent = (zbx_lld_item_t *)item->dependent_items.values[index];
2673 		dependent->master_itemid = item->itemid;
2674 		lld_item_save(hostid, item_prototypes, dependent, itemid, itemdiscoveryid, db_insert,
2675 				db_insert_idiscovery);
2676 	}
2677 }
2678 
2679 /******************************************************************************
2680  *                                                                            *
2681  * Function: lld_item_prepare_update                                          *
2682  *                                                                            *
2683  * Purpose: prepare sql to update LLD item                                    *
2684  *                                                                            *
2685  * Parameters: item_prototype       - [IN] item prototype                     *
2686  *             item                 - [IN] item to be updated                 *
2687  *             sql                  - [IN/OUT] sql buffer pointer used for    *
2688  *                                             update operations              *
2689  *             sql_alloc            - [IN/OUT] sql buffer already allocated   *
2690  *                                             memory                         *
2691  *             sql_offset           - [IN/OUT] offset for writing within sql  *
2692  *                                             buffer                         *
2693  *                                                                            *
2694  ******************************************************************************/
lld_item_prepare_update(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_item_t * item,char ** sql,size_t * sql_alloc,size_t * sql_offset)2695 static void	lld_item_prepare_update(const zbx_lld_item_prototype_t *item_prototype, const zbx_lld_item_t *item,
2696 		char **sql, size_t *sql_alloc, size_t *sql_offset)
2697 {
2698 	char				*value_esc;
2699 	const char			*d = "";
2700 
2701 	zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "update items set ");
2702 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_NAME))
2703 	{
2704 		value_esc = DBdyn_escape_string(item->name);
2705 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "name='%s'", value_esc);
2706 		zbx_free(value_esc);
2707 		d = ",";
2708 	}
2709 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
2710 	{
2711 		value_esc = DBdyn_escape_string(item->key);
2712 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%skey_='%s'", d, value_esc);
2713 		zbx_free(value_esc);
2714 		d = ",";
2715 	}
2716 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TYPE))
2717 	{
2718 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%stype=%d", d, (int)item_prototype->type);
2719 		d = ",";
2720 	}
2721 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE))
2722 	{
2723 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%svalue_type=%d", d, (int)item_prototype->value_type);
2724 		d = ",";
2725 	}
2726 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DELAY))
2727 	{
2728 		value_esc = DBdyn_escape_string(item->delay);
2729 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sdelay='%s'", d, value_esc);
2730 		zbx_free(value_esc);
2731 		d = ",";
2732 	}
2733 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY))
2734 	{
2735 		value_esc = DBdyn_escape_string(item->history);
2736 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%shistory='%s'", d, value_esc);
2737 		zbx_free(value_esc);
2738 		d = ",";
2739 	}
2740 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS))
2741 	{
2742 		value_esc = DBdyn_escape_string(item->trends);
2743 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%strends='%s'", d, value_esc);
2744 		zbx_free(value_esc);
2745 		d = ",";
2746 	}
2747 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS))
2748 	{
2749 		value_esc = DBdyn_escape_string(item_prototype->trapper_hosts);
2750 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%strapper_hosts='%s'", d, value_esc);
2751 		zbx_free(value_esc);
2752 		d = ",";
2753 	}
2754 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_UNITS))
2755 	{
2756 		value_esc = DBdyn_escape_string(item->units);
2757 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sunits='%s'", d, value_esc);
2758 		zbx_free(value_esc);
2759 		d = ",";
2760 	}
2761 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA))
2762 	{
2763 		value_esc = DBdyn_escape_string(item_prototype->formula);
2764 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sformula='%s'", d, value_esc);
2765 		zbx_free(value_esc);
2766 		d = ",";
2767 	}
2768 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT))
2769 	{
2770 		value_esc = DBdyn_escape_string(item_prototype->logtimefmt);
2771 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%slogtimefmt='%s'", d, value_esc);
2772 		zbx_free(value_esc);
2773 		d = ",";
2774 	}
2775 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID))
2776 	{
2777 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%svaluemapid=%s",
2778 				d, DBsql_id_ins(item_prototype->valuemapid));
2779 		d = ",";
2780 	}
2781 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS))
2782 	{
2783 		value_esc = DBdyn_escape_string(item->params);
2784 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sparams='%s'", d, value_esc);
2785 		zbx_free(value_esc);
2786 		d = ",";
2787 	}
2788 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR))
2789 	{
2790 		value_esc = DBdyn_escape_string(item->ipmi_sensor);
2791 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sipmi_sensor='%s'", d, value_esc);
2792 		zbx_free(value_esc);
2793 		d = ",";
2794 	}
2795 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY))
2796 	{
2797 		value_esc = DBdyn_escape_string(item_prototype->snmp_community);
2798 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmp_community='%s'", d, value_esc);
2799 		zbx_free(value_esc);
2800 		d = ",";
2801 	}
2802 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID))
2803 	{
2804 		value_esc = DBdyn_escape_string(item->snmp_oid);
2805 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmp_oid='%s'", d, value_esc);
2806 		zbx_free(value_esc);
2807 		d = ",";
2808 	}
2809 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PORT))
2810 	{
2811 		value_esc = DBdyn_escape_string(item_prototype->port);
2812 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sport='%s'", d, value_esc);
2813 		zbx_free(value_esc);
2814 		d = ",";
2815 	}
2816 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME))
2817 	{
2818 		value_esc = DBdyn_escape_string(item_prototype->snmpv3_securityname);
2819 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_securityname='%s'", d, value_esc);
2820 		zbx_free(value_esc);
2821 		d = ",";
2822 	}
2823 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL))
2824 	{
2825 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_securitylevel=%d", d,
2826 				(int)item_prototype->snmpv3_securitylevel);
2827 		d = ",";
2828 	}
2829 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL))
2830 	{
2831 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_authprotocol=%d", d,
2832 				(int)item_prototype->snmpv3_authprotocol);
2833 		d = ",";
2834 	}
2835 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE))
2836 	{
2837 		value_esc = DBdyn_escape_string(item_prototype->snmpv3_authpassphrase);
2838 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_authpassphrase='%s'", d, value_esc);
2839 		zbx_free(value_esc);
2840 		d = ",";
2841 	}
2842 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL))
2843 	{
2844 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_privprotocol=%d", d,
2845 				(int)item_prototype->snmpv3_privprotocol);
2846 		d = ",";
2847 	}
2848 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE))
2849 	{
2850 		value_esc = DBdyn_escape_string(item_prototype->snmpv3_privpassphrase);
2851 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_privpassphrase='%s'", d, value_esc);
2852 		zbx_free(value_esc);
2853 		d = ",";
2854 	}
2855 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE))
2856 	{
2857 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sauthtype=%d", d, (int)item_prototype->authtype);
2858 		d = ",";
2859 	}
2860 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME))
2861 	{
2862 		value_esc = DBdyn_escape_string(item->username);
2863 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%susername='%s'", d, value_esc);
2864 		zbx_free(value_esc);
2865 		d = ",";
2866 	}
2867 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD))
2868 	{
2869 		value_esc = DBdyn_escape_string(item->password);
2870 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%spassword='%s'", d, value_esc);
2871 		zbx_free(value_esc);
2872 		d = ",";
2873 	}
2874 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY))
2875 	{
2876 		value_esc = DBdyn_escape_string(item_prototype->publickey);
2877 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%spublickey='%s'", d, value_esc);
2878 		zbx_free(value_esc);
2879 		d = ",";
2880 	}
2881 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY))
2882 	{
2883 		value_esc = DBdyn_escape_string(item_prototype->privatekey);
2884 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sprivatekey='%s'", d, value_esc);
2885 		zbx_free(value_esc);
2886 		d = ",";
2887 	}
2888 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION))
2889 	{
2890 		value_esc = DBdyn_escape_string(item->description);
2891 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sdescription='%s'", d, value_esc);
2892 		zbx_free(value_esc);
2893 		d = ",";
2894 
2895 	}
2896 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID))
2897 	{
2898 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sinterfaceid=%s",
2899 				d, DBsql_id_ins(item_prototype->interfaceid));
2900 		d = ",";
2901 	}
2902 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME))
2903 	{
2904 		value_esc = DBdyn_escape_string(item_prototype->snmpv3_contextname);
2905 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_contextname='%s'", d, value_esc);
2906 		zbx_free(value_esc);
2907 		d = ",";
2908 	}
2909 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_JMX_ENDPOINT))
2910 	{
2911 		value_esc = DBdyn_escape_string(item->jmx_endpoint);
2912 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sjmx_endpoint='%s'", d, value_esc);
2913 		zbx_free(value_esc);
2914 		d = ",";
2915 	}
2916 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_MASTER_ITEM))
2917 	{
2918 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%smaster_itemid=%s",
2919 				d, DBsql_id_ins(item->master_itemid));
2920 		d = ",";
2921 	}
2922 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TIMEOUT))
2923 	{
2924 		value_esc = DBdyn_escape_string(item->timeout);
2925 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%stimeout='%s'", d, value_esc);
2926 		zbx_free(value_esc);
2927 		d = ",";
2928 	}
2929 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_URL))
2930 	{
2931 		value_esc = DBdyn_escape_string(item->url);
2932 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%surl='%s'", d, value_esc);
2933 		zbx_free(value_esc);
2934 		d = ",";
2935 	}
2936 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_QUERY_FIELDS))
2937 	{
2938 		value_esc = DBdyn_escape_string(item->query_fields);
2939 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%squery_fields='%s'", d, value_esc);
2940 		zbx_free(value_esc);
2941 		d = ",";
2942 	}
2943 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_POSTS))
2944 	{
2945 		value_esc = DBdyn_escape_string(item->posts);
2946 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sposts='%s'", d, value_esc);
2947 		zbx_free(value_esc);
2948 		d = ",";
2949 	}
2950 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_STATUS_CODES))
2951 	{
2952 		value_esc = DBdyn_escape_string(item->status_codes);
2953 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sstatus_codes='%s'", d, value_esc);
2954 		zbx_free(value_esc);
2955 		d = ",";
2956 	}
2957 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_FOLLOW_REDIRECTS))
2958 	{
2959 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sfollow_redirects=%d", d,
2960 				(int)item_prototype->follow_redirects);
2961 		d = ",";
2962 	}
2963 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_POST_TYPE))
2964 	{
2965 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%spost_type=%d", d, (int)item_prototype->post_type);
2966 		d = ",";
2967 	}
2968 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_HTTP_PROXY))
2969 	{
2970 		value_esc = DBdyn_escape_string(item->http_proxy);
2971 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%shttp_proxy='%s'", d, value_esc);
2972 		zbx_free(value_esc);
2973 		d = ",";
2974 	}
2975 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_HEADERS))
2976 	{
2977 		value_esc = DBdyn_escape_string(item->headers);
2978 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sheaders='%s'", d, value_esc);
2979 		zbx_free(value_esc);
2980 		d = ",";
2981 	}
2982 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_RETRIEVE_MODE))
2983 	{
2984 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sretrieve_mode=%d", d,
2985 				(int)item_prototype->retrieve_mode);
2986 		d = ",";
2987 	}
2988 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_REQUEST_METHOD))
2989 	{
2990 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%srequest_method=%d", d,
2991 				(int)item_prototype->request_method);
2992 		d = ",";
2993 	}
2994 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_OUTPUT_FORMAT))
2995 	{
2996 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%soutput_format=%d", d,
2997 				(int)item_prototype->output_format);
2998 		d = ",";
2999 	}
3000 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SSL_CERT_FILE))
3001 	{
3002 		value_esc = DBdyn_escape_string(item->ssl_cert_file);
3003 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sssl_cert_file='%s'", d, value_esc);
3004 		zbx_free(value_esc);
3005 		d = ",";
3006 	}
3007 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_FILE))
3008 	{
3009 		value_esc = DBdyn_escape_string(item->ssl_key_file);
3010 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sssl_key_file='%s'", d, value_esc);
3011 		zbx_free(value_esc);
3012 		d = ",";
3013 	}
3014 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_PASSWORD))
3015 	{
3016 		value_esc = DBdyn_escape_string(item->ssl_key_password);
3017 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sssl_key_password='%s'", d, value_esc);
3018 		zbx_free(value_esc);
3019 		d = ",";
3020 	}
3021 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_PEER))
3022 	{
3023 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sverify_peer=%d", d, (int)item_prototype->verify_peer);
3024 		d = ",";
3025 	}
3026 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_HOST))
3027 	{
3028 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sverify_host=%d", d, (int)item_prototype->verify_host);
3029 		d = ",";
3030 	}
3031 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_ALLOW_TRAPS))
3032 	{
3033 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sallow_traps=%d", d, (int)item_prototype->allow_traps);
3034 	}
3035 
3036 	zbx_snprintf_alloc(sql, sql_alloc, sql_offset, " where itemid=" ZBX_FS_UI64 ";\n", item->itemid);
3037 
3038 	DBexecute_overflowed_sql(sql, sql_alloc, sql_offset);
3039 }
3040 
3041 /******************************************************************************
3042  *                                                                            *
3043  * Function: lld_item_discovery_prepare_update                                *
3044  *                                                                            *
3045  * Purpose: prepare sql to update key in LLD item discovery                   *
3046  *                                                                            *
3047  * Parameters: item_prototype       - [IN] item prototype                     *
3048  *             item                 - [IN] item to be updated                 *
3049  *             sql                  - [IN/OUT] sql buffer pointer used for    *
3050  *                                             update operations              *
3051  *             sql_alloc            - [IN/OUT] sql buffer already allocated   *
3052  *                                             memory                         *
3053  *             sql_offset           - [IN/OUT] offset for writing within sql  *
3054  *                                             buffer                         *
3055  *                                                                            *
3056  ******************************************************************************/
lld_item_discovery_prepare_update(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_item_t * item,char ** sql,size_t * sql_alloc,size_t * sql_offset)3057 static void lld_item_discovery_prepare_update(const zbx_lld_item_prototype_t *item_prototype,
3058 		const zbx_lld_item_t *item, char **sql, size_t *sql_alloc, size_t *sql_offset)
3059 {
3060 	char	*value_esc;
3061 
3062 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
3063 	{
3064 		value_esc = DBdyn_escape_string(item_prototype->key);
3065 		zbx_snprintf_alloc(sql, sql_alloc, sql_offset,
3066 				"update item_discovery"
3067 				" set key_='%s'"
3068 				" where itemid=" ZBX_FS_UI64 ";\n",
3069 				value_esc, item->itemid);
3070 		zbx_free(value_esc);
3071 
3072 		DBexecute_overflowed_sql(sql, sql_alloc, sql_offset);
3073 	}
3074 }
3075 
3076 
3077 /******************************************************************************
3078  *                                                                            *
3079  * Function: lld_items_save                                                   *
3080  *                                                                            *
3081  * Parameters: hostid          - [IN] parent host id                          *
3082  *             item_prototypes - [IN] item prototypes                         *
3083  *             items           - [IN/OUT] items to save                       *
3084  *             items_index     - [IN] LLD item index                          *
3085  *             host_locked     - [IN/OUT] host record is locked               *
3086  *                                                                            *
3087  * Return value: SUCCEED - if items were successfully saved or saving was not *
3088  *                         necessary                                          *
3089  *               FAIL    - items cannot be saved                              *
3090  *                                                                            *
3091  ******************************************************************************/
lld_items_save(zbx_uint64_t hostid,const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * items,zbx_hashset_t * items_index,int * host_locked)3092 static int	lld_items_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *items,
3093 		zbx_hashset_t *items_index, int *host_locked)
3094 {
3095 	const char			*__function_name = "lld_items_save";
3096 
3097 	int				ret = SUCCEED, i, new_items = 0, upd_items = 0;
3098 	zbx_lld_item_t			*item;
3099 	zbx_uint64_t			itemid, itemdiscoveryid;
3100 	zbx_db_insert_t			db_insert, db_insert_idiscovery;
3101 	zbx_lld_item_index_t		item_index_local;
3102 	zbx_vector_uint64_t		upd_keys, item_protoids;
3103 	char				*sql = NULL;
3104 	size_t				sql_alloc = 8 * ZBX_KIBIBYTE, sql_offset = 0;
3105 	const zbx_lld_item_prototype_t	*item_prototype;
3106 
3107 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3108 
3109 	zbx_vector_uint64_create(&upd_keys);
3110 	zbx_vector_uint64_create(&item_protoids);
3111 
3112 	if (0 == items->values_num)
3113 		goto out;
3114 
3115 	for (i = 0; i < items->values_num; i++)
3116 	{
3117 		item = (zbx_lld_item_t *)items->values[i];
3118 
3119 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3120 			continue;
3121 
3122 		if (0 == item->itemid)
3123 		{
3124 			new_items++;
3125 		}
3126 		else if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE))
3127 		{
3128 			upd_items++;
3129 			if(0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
3130 				zbx_vector_uint64_append(&upd_keys, item->itemid);
3131 		}
3132 	}
3133 
3134 	if (0 == new_items && 0 == upd_items)
3135 		goto out;
3136 
3137 	if (0 == *host_locked)
3138 	{
3139 		if (SUCCEED != DBlock_hostid(hostid))
3140 		{
3141 			/* the host was removed while processing lld rule */
3142 			ret = FAIL;
3143 			goto out;
3144 		}
3145 
3146 		*host_locked = 1;
3147 	}
3148 
3149 	for (i = 0; i < item_prototypes->values_num; i++)
3150 	{
3151 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
3152 		zbx_vector_uint64_append(&item_protoids, item_prototype->itemid);
3153 	}
3154 
3155 	if (SUCCEED != DBlock_itemids(&item_protoids))
3156 	{
3157 		/* the item prototype was removed while processing lld rule */
3158 		ret = FAIL;
3159 		goto out;
3160 	}
3161 
3162 	if (0 != upd_items)
3163 		sql = (char*)zbx_malloc(NULL, sql_alloc);
3164 
3165 	if (0 != upd_keys.values_num)
3166 	{
3167 		sql_offset = 0;
3168 
3169 		zbx_vector_uint64_sort(&upd_keys, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3170 
3171 #ifdef HAVE_MYSQL
3172 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update items set key_=concat('#',key_) where");
3173 #else
3174 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update items set key_='#'||key_ where");
3175 #endif
3176 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", upd_keys.values,
3177 				upd_keys.values_num);
3178 
3179 		if (ZBX_DB_OK > DBexecute("%s", sql))
3180 		{
3181 			ret = FAIL;
3182 			goto out;
3183 		}
3184 
3185 	}
3186 
3187 	if (0 != new_items)
3188 	{
3189 		itemid = DBget_maxid_num("items", new_items);
3190 		itemdiscoveryid = DBget_maxid_num("item_discovery", new_items);
3191 
3192 		zbx_db_insert_prepare(&db_insert, "items", "itemid", "name", "key_", "hostid", "type", "value_type",
3193 				"delay", "history", "trends", "status", "trapper_hosts",
3194 				"units", "formula", "logtimefmt", "valuemapid", "params",
3195 				"ipmi_sensor", "snmp_community", "snmp_oid", "port", "snmpv3_securityname",
3196 				"snmpv3_securitylevel", "snmpv3_authprotocol", "snmpv3_authpassphrase",
3197 				"snmpv3_privprotocol", "snmpv3_privpassphrase", "authtype", "username", "password",
3198 				"publickey", "privatekey", "description", "interfaceid", "flags", "snmpv3_contextname",
3199 				"jmx_endpoint", "master_itemid", "timeout", "url", "query_fields", "posts",
3200 				"status_codes", "follow_redirects", "post_type", "http_proxy", "headers",
3201 				"retrieve_mode", "request_method", "output_format", "ssl_cert_file", "ssl_key_file",
3202 				"ssl_key_password", "verify_peer", "verify_host", "allow_traps", NULL);
3203 
3204 		zbx_db_insert_prepare(&db_insert_idiscovery, "item_discovery", "itemdiscoveryid", "itemid",
3205 				"parent_itemid", "key_", NULL);
3206 	}
3207 
3208 	for (i = 0; i < items->values_num; i++)
3209 	{
3210 		item = (zbx_lld_item_t *)items->values[i];
3211 
3212 		/* dependent items based on item prototypes are saved within recursive lld_item_save calls while */
3213 		/* saving master item */
3214 		if (0 == item->master_itemid)
3215 		{
3216 			lld_item_save(hostid, item_prototypes, item, &itemid, &itemdiscoveryid, &db_insert,
3217 					&db_insert_idiscovery);
3218 		}
3219 		else
3220 		{
3221 			item_index_local.parent_itemid = item->master_itemid;
3222 			item_index_local.lld_row = (zbx_lld_row_t *)item->lld_row;
3223 
3224 			/* dependent item based on host item should be saved */
3225 			if (NULL == zbx_hashset_search(items_index, &item_index_local))
3226 			{
3227 				lld_item_save(hostid, item_prototypes, item, &itemid, &itemdiscoveryid, &db_insert,
3228 						&db_insert_idiscovery);
3229 			}
3230 		}
3231 
3232 	}
3233 
3234 	if (0 != new_items)
3235 	{
3236 		zbx_db_insert_execute(&db_insert);
3237 		zbx_db_insert_clean(&db_insert);
3238 
3239 		zbx_db_insert_execute(&db_insert_idiscovery);
3240 		zbx_db_insert_clean(&db_insert_idiscovery);
3241 
3242 		zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3243 	}
3244 
3245 	if (0 != upd_items)
3246 	{
3247 		int	index;
3248 
3249 		sql_offset = 0;
3250 
3251 		DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3252 
3253 		for (i = 0; i < items->values_num; i++)
3254 		{
3255 			item = (zbx_lld_item_t *)items->values[i];
3256 
3257 			if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED) ||
3258 					0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE))
3259 			{
3260 				continue;
3261 			}
3262 
3263 			if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
3264 					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3265 			{
3266 				THIS_SHOULD_NEVER_HAPPEN;
3267 				continue;
3268 			}
3269 
3270 			item_prototype = item_prototypes->values[index];
3271 
3272 			lld_item_prepare_update(item_prototype, item, &sql, &sql_alloc, &sql_offset);
3273 			lld_item_discovery_prepare_update(item_prototype, item, &sql, &sql_alloc, &sql_offset);
3274 		}
3275 
3276 		DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3277 		if (sql_offset > 16)
3278 			DBexecute("%s", sql);
3279 	}
3280 out:
3281 	zbx_free(sql);
3282 	zbx_vector_uint64_destroy(&item_protoids);
3283 	zbx_vector_uint64_destroy(&upd_keys);
3284 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3285 
3286 	return ret;
3287 }
3288 
3289 /******************************************************************************
3290  *                                                                            *
3291  * Function: lld_items_preproc_save                                           *
3292  *                                                                            *
3293  * Purpose: saves/updates/removes item preprocessing operations               *
3294  *                                                                            *
3295  * Parameters: hostid      - [IN] parent host id                              *
3296  *             items       - [IN] items                                       *
3297  *             host_locked - [IN/OUT] host record is locked                   *
3298  *                                                                            *
3299  ******************************************************************************/
lld_items_preproc_save(zbx_uint64_t hostid,zbx_vector_ptr_t * items,int * host_locked)3300 static int	lld_items_preproc_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, int *host_locked)
3301 {
3302 	const char		*__function_name = "lld_items_preproc_save";
3303 
3304 	int			ret = SUCCEED, i, j, new_preproc_num = 0, update_preproc_num = 0, delete_preproc_num = 0;
3305 	zbx_lld_item_t		*item;
3306 	zbx_lld_item_preproc_t	*preproc_op;
3307 	zbx_vector_uint64_t	deleteids;
3308 	zbx_db_insert_t		db_insert;
3309 	char			*sql = NULL;
3310 	size_t			sql_alloc = 0, sql_offset = 0;
3311 
3312 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3313 
3314 	zbx_vector_uint64_create(&deleteids);
3315 
3316 	for (i = 0; i < items->values_num; i++)
3317 	{
3318 		item = (zbx_lld_item_t *)items->values[i];
3319 
3320 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3321 			continue;
3322 
3323 		for (j = 0; j < item->preproc_ops.values_num; j++)
3324 		{
3325 			preproc_op = (zbx_lld_item_preproc_t *)item->preproc_ops.values[j];
3326 			if (0 == (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED))
3327 			{
3328 				zbx_vector_uint64_append(&deleteids, preproc_op->item_preprocid);
3329 				continue;
3330 			}
3331 
3332 			if (0 == preproc_op->item_preprocid)
3333 			{
3334 				new_preproc_num++;
3335 				continue;
3336 			}
3337 
3338 			if (0 == (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE))
3339 				continue;
3340 
3341 			update_preproc_num++;
3342 		}
3343 	}
3344 
3345 	if (0 == *host_locked && (0 != update_preproc_num || 0 != new_preproc_num || 0 != deleteids.values_num))
3346 	{
3347 		if (SUCCEED != DBlock_hostid(hostid))
3348 		{
3349 			/* the host was removed while processing lld rule */
3350 			ret = FAIL;
3351 			goto out;
3352 		}
3353 
3354 		*host_locked = 1;
3355 	}
3356 
3357 	if (0 != update_preproc_num)
3358 	{
3359 		DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3360 	}
3361 
3362 	if (0 != new_preproc_num)
3363 	{
3364 		zbx_db_insert_prepare(&db_insert, "item_preproc", "item_preprocid", "itemid", "step", "type", "params",
3365 				NULL);
3366 	}
3367 
3368 	for (i = 0; i < items->values_num; i++)
3369 	{
3370 		item = (zbx_lld_item_t *)items->values[i];
3371 
3372 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3373 			continue;
3374 
3375 		for (j = 0; j < item->preproc_ops.values_num; j++)
3376 		{
3377 			char	delim = ' ';
3378 
3379 			preproc_op = (zbx_lld_item_preproc_t *)item->preproc_ops.values[j];
3380 
3381 			if (0 == preproc_op->item_preprocid)
3382 			{
3383 				zbx_db_insert_add_values(&db_insert, __UINT64_C(0), item->itemid, preproc_op->step,
3384 						preproc_op->type, preproc_op->params);
3385 				continue;
3386 			}
3387 
3388 			if (0 == (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE))
3389 				continue;
3390 
3391 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update item_preproc set");
3392 
3393 			if (0 != (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_TYPE))
3394 			{
3395 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%ctype=%d", delim, preproc_op->type);
3396 				delim = ',';
3397 			}
3398 
3399 			if (0 != (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_STEP))
3400 			{
3401 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cstep=%d", delim, preproc_op->step);
3402 				delim = ',';
3403 			}
3404 
3405 			if (0 != (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_PARAMS))
3406 			{
3407 				char	*params_esc;
3408 
3409 				params_esc = DBdyn_escape_string(preproc_op->params);
3410 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cparams='%s'", delim, params_esc);
3411 
3412 				zbx_free(params_esc);
3413 			}
3414 
3415 			zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where item_preprocid=" ZBX_FS_UI64 ";\n",
3416 					preproc_op->item_preprocid);
3417 
3418 			DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3419 		}
3420 	}
3421 
3422 	if (0 != update_preproc_num)
3423 	{
3424 		DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3425 
3426 		if (16 < sql_offset)	/* in ORACLE always present begin..end; */
3427 			DBexecute("%s", sql);
3428 	}
3429 
3430 	if (0 != new_preproc_num)
3431 	{
3432 		zbx_db_insert_autoincrement(&db_insert, "item_preprocid");
3433 		zbx_db_insert_execute(&db_insert);
3434 		zbx_db_insert_clean(&db_insert);
3435 	}
3436 
3437 	if (0 != deleteids.values_num)
3438 	{
3439 		sql_offset = 0;
3440 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from item_preproc where");
3441 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "item_preprocid", deleteids.values,
3442 				deleteids.values_num);
3443 		DBexecute("%s", sql);
3444 
3445 		delete_preproc_num = deleteids.values_num;
3446 	}
3447 out:
3448 	zbx_free(sql);
3449 	zbx_vector_uint64_destroy(&deleteids);
3450 
3451 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() added:%d updated:%d removed:%d", __function_name, new_preproc_num,
3452 			update_preproc_num, delete_preproc_num);
3453 
3454 	return ret;
3455 }
3456 
3457 /******************************************************************************
3458  *                                                                            *
3459  * Function: lld_applications_save                                            *
3460  *                                                                            *
3461  * Parameters: hostid                 - [IN] host id                          *
3462  *             applications           - [IN/OUT] applications to save         *
3463  *             application_prototypes - [IN] the application prototypes       *
3464  *             host_locked            - [IN/OUT] host record is locked        *
3465  *                                                                            *
3466  ******************************************************************************/
lld_applications_save(zbx_uint64_t hostid,zbx_vector_ptr_t * applications,const zbx_vector_ptr_t * application_prototypes,int * host_locked)3467 static int	lld_applications_save(zbx_uint64_t hostid, zbx_vector_ptr_t *applications,
3468 		const zbx_vector_ptr_t *application_prototypes, int *host_locked)
3469 {
3470 	const char				*__function_name = "lld_applications_save";
3471 	int					ret = SUCCEED, i, new_applications = 0, new_discoveries = 0, index;
3472 	zbx_lld_application_t			*application;
3473 	const zbx_lld_application_prototype_t	*application_prototype;
3474 	zbx_uint64_t				applicationid, application_discoveryid;
3475 	zbx_db_insert_t				db_insert, db_insert_discovery;
3476 	zbx_vector_uint64_t			del_applicationids, del_discoveryids;
3477 	char					*sql_a = NULL, *sql_ad = NULL, *name;
3478 	size_t					sql_a_alloc = 0, sql_a_offset = 0, sql_ad_alloc = 0, sql_ad_offset = 0;
3479 
3480 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3481 
3482 	if (0 == applications->values_num)
3483 		goto out;
3484 
3485 	if (0 == *host_locked)
3486 	{
3487 		if (SUCCEED != DBlock_hostid(hostid))
3488 		{
3489 			/* the host was removed while processing lld rule */
3490 			ret = FAIL;
3491 			goto out;
3492 		}
3493 
3494 		*host_locked = 1;
3495 	}
3496 
3497 	zbx_vector_uint64_create(&del_applicationids);
3498 	zbx_vector_uint64_create(&del_discoveryids);
3499 
3500 	/* Count new applications and application discoveries.                      */
3501 	/* Note that an application might have been discovered by another lld rule. */
3502 	/* In this case the discovered items will be linked to this application and */
3503 	/* new application discovery record, linking the prototype to this          */
3504 	/* application, will be created.                                            */
3505 	for (i = 0; i < applications->values_num; i++)
3506 	{
3507 		application = (zbx_lld_application_t *)applications->values[i];
3508 
3509 		if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_REMOVE))
3510 		{
3511 			zbx_vector_uint64_append(&del_applicationids, application->applicationid);
3512 			continue;
3513 		}
3514 
3515 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
3516 			continue;
3517 
3518 		if (0 == application->applicationid)
3519 			new_applications++;
3520 
3521 		if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY))
3522 			new_discoveries++;
3523 	}
3524 
3525 	/* insert new applications, application discoveries and prepare a list of applications to be removed */
3526 
3527 	if (0 != new_applications)
3528 	{
3529 		applicationid = DBget_maxid_num("applications", new_applications);
3530 		zbx_db_insert_prepare(&db_insert, "applications", "applicationid", "hostid", "name", "flags", NULL);
3531 	}
3532 
3533 	if (0 != new_discoveries)
3534 	{
3535 		application_discoveryid = DBget_maxid_num("application_discovery", new_discoveries);
3536 		zbx_db_insert_prepare(&db_insert_discovery, "application_discovery", "application_discoveryid",
3537 				"applicationid", "application_prototypeid", "name", NULL);
3538 	}
3539 
3540 	for (i = 0; i < applications->values_num; i++)
3541 	{
3542 		application = (zbx_lld_application_t *)applications->values[i];
3543 
3544 		if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY))
3545 		{
3546 			zbx_vector_uint64_append(&del_discoveryids, application->application_discoveryid);
3547 			continue;
3548 		}
3549 
3550 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
3551 			continue;
3552 
3553 		if (FAIL == (index = zbx_vector_ptr_search(application_prototypes,
3554 				&application->application_prototypeid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3555 		{
3556 			THIS_SHOULD_NEVER_HAPPEN;
3557 			continue;
3558 		}
3559 
3560 		application_prototype = (zbx_lld_application_prototype_t *)application_prototypes->values[index];
3561 
3562 		if (0 == application->applicationid)
3563 		{
3564 			application->applicationid = applicationid++;
3565 			zbx_db_insert_add_values(&db_insert, application->applicationid, hostid, application->name,
3566 					ZBX_FLAG_DISCOVERY_CREATED);
3567 		}
3568 
3569 		if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
3570 		{
3571 			if (NULL == sql_a)
3572 				DBbegin_multiple_update(&sql_a, &sql_a_alloc, &sql_a_offset);
3573 			if (NULL == sql_ad)
3574 				DBbegin_multiple_update(&sql_ad, &sql_ad_alloc, &sql_ad_offset);
3575 
3576 			name = DBdyn_escape_string(application->name);
3577 			zbx_snprintf_alloc(&sql_a, &sql_a_alloc, &sql_a_offset,
3578 					"update applications set name='%s'"
3579 					" where applicationid=" ZBX_FS_UI64 ";\n",
3580 					name, application->applicationid);
3581 			zbx_free(name);
3582 
3583 			name = DBdyn_escape_string(application_prototype->name);
3584 			zbx_snprintf_alloc(&sql_ad, &sql_ad_alloc, &sql_ad_offset,
3585 					"update application_discovery set name='%s'"
3586 					" where application_discoveryid=" ZBX_FS_UI64 ";\n",
3587 					name, application->application_discoveryid);
3588 			zbx_free(name);
3589 
3590 			DBexecute_overflowed_sql(&sql_a, &sql_a_alloc, &sql_a_offset);
3591 			DBexecute_overflowed_sql(&sql_ad, &sql_ad_alloc, &sql_ad_offset);
3592 
3593 			continue;
3594 		}
3595 
3596 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY))
3597 			continue;
3598 
3599 		application->application_discoveryid = application_discoveryid++;
3600 		zbx_db_insert_add_values(&db_insert_discovery, application->application_discoveryid,
3601 				application->applicationid, application->application_prototypeid,
3602 				application_prototype->name);
3603 	}
3604 
3605 	if (NULL != sql_a)
3606 	{
3607 		DBend_multiple_update(&sql_a, &sql_a_alloc, &sql_a_offset);
3608 
3609 		if (16 < sql_a_offset)	/* in ORACLE always present begin..end; */
3610 			DBexecute("%s", sql_a);
3611 	}
3612 
3613 	if (NULL != sql_ad)
3614 	{
3615 		DBend_multiple_update(&sql_ad, &sql_ad_alloc, &sql_ad_offset);
3616 
3617 		if (16 < sql_ad_offset)
3618 			DBexecute("%s", sql_ad);
3619 	}
3620 
3621 	if (0 != del_applicationids.values_num)
3622 	{
3623 		sql_a_offset = 0;
3624 
3625 		zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "delete from applications where");
3626 		DBadd_condition_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "applicationid", del_applicationids.values,
3627 				del_applicationids.values_num);
3628 		zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, ";\n");
3629 
3630 		DBexecute("%s", sql_a);
3631 	}
3632 
3633 	if (0 != del_discoveryids.values_num)
3634 	{
3635 		sql_ad_offset = 0;
3636 
3637 		zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "delete from application_discovery where");
3638 		DBadd_condition_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "application_discoveryid",
3639 				del_discoveryids.values, del_discoveryids.values_num);
3640 		zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, ";\n");
3641 
3642 		DBexecute("%s", sql_ad);
3643 	}
3644 
3645 	zbx_free(sql_a);
3646 	zbx_free(sql_ad);
3647 
3648 	if (0 != new_applications)
3649 	{
3650 		zbx_db_insert_execute(&db_insert);
3651 		zbx_db_insert_clean(&db_insert);
3652 
3653 		zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3654 	}
3655 
3656 	if (0 != new_discoveries)
3657 	{
3658 		zbx_db_insert_execute(&db_insert_discovery);
3659 		zbx_db_insert_clean(&db_insert_discovery);
3660 	}
3661 
3662 	zbx_vector_uint64_destroy(&del_discoveryids);
3663 	zbx_vector_uint64_destroy(&del_applicationids);
3664 out:
3665 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3666 
3667 	return ret;
3668 }
3669 
3670 /******************************************************************************
3671  *                                                                            *
3672  * Function: lld_item_application_validate                                    *
3673  *                                                                            *
3674  * Purpose: validates undiscovered item-application link to determine if it   *
3675  *          should be removed                                                 *
3676  *                                                                            *
3677  * Parameters: items_application - [IN] an item-application link to validate  *
3678  *             items             - [IN] the related items                     *
3679  *                                                                            *
3680  * Return value: SUCCEED - item-application link should not be removed        *
3681  *               FAIL    - item-application link should be removed            *
3682  *                                                                            *
3683  * Comments: Undiscovered item-application link must be removed if item was   *
3684  *           discovered.                                                      *
3685  *                                                                            *
3686  ******************************************************************************/
lld_item_application_validate(const zbx_lld_item_application_t * item_application,const zbx_vector_ptr_t * items)3687 static int	lld_item_application_validate(const zbx_lld_item_application_t *item_application,
3688 		const zbx_vector_ptr_t *items)
3689 {
3690 	int	index;
3691 
3692 	if (FAIL == (index = zbx_vector_ptr_bsearch(items, &item_application->item_ref.itemid,
3693 			ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3694 	{
3695 		THIS_SHOULD_NEVER_HAPPEN;
3696 		return FAIL;
3697 	}
3698 
3699 	return 0 != (((zbx_lld_item_t *)items->values[index])->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED) ? FAIL : SUCCEED;
3700 }
3701 
3702 /******************************************************************************
3703  *                                                                            *
3704  * Function: lld_items_applications_save                                      *
3705  *                                                                            *
3706  * Parameters: items_applications - [IN] item-application links               *
3707  *                                                                            *
3708  ******************************************************************************/
lld_items_applications_save(zbx_hashset_t * items_applications,const zbx_vector_ptr_t * items)3709 static void	lld_items_applications_save(zbx_hashset_t *items_applications, const zbx_vector_ptr_t *items)
3710 {
3711 	const char			*__function_name = "lld_items_applications_save";
3712 	zbx_hashset_iter_t		iter;
3713 	zbx_lld_item_application_t	*item_application;
3714 	zbx_vector_uint64_t		del_itemappids;
3715 	int				new_item_applications = 0;
3716 	zbx_uint64_t			itemappid, applicationid, itemid;
3717 	zbx_db_insert_t			db_insert;
3718 
3719 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3720 
3721 	if (0 == items_applications->num_data)
3722 		goto out;
3723 
3724 	zbx_vector_uint64_create(&del_itemappids);
3725 
3726 	/* count new item-application links */
3727 	zbx_hashset_iter_reset(items_applications, &iter);
3728 
3729 	while (NULL != (item_application = (zbx_lld_item_application_t *)zbx_hashset_iter_next(&iter)))
3730 	{
3731 		if (0 == item_application->itemappid)
3732 			new_item_applications++;
3733 	}
3734 
3735 	if (0 != new_item_applications)
3736 	{
3737 		itemappid = DBget_maxid_num("items_applications", new_item_applications);
3738 		zbx_db_insert_prepare(&db_insert, "items_applications", "itemappid", "applicationid", "itemid", NULL);
3739 	}
3740 
3741 	zbx_hashset_iter_reset(items_applications, &iter);
3742 
3743 	while (NULL != (item_application = (zbx_lld_item_application_t *)zbx_hashset_iter_next(&iter)))
3744 	{
3745 		if (0 != item_application->itemappid)
3746 		{
3747 			/* add for removal the old links that aren't discovered and can be removed */
3748 			if (0 == (item_application->flags & ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED) &&
3749 					FAIL == lld_item_application_validate(item_application, items))
3750 			{
3751 				zbx_vector_uint64_append(&del_itemappids, item_application->itemappid);
3752 			}
3753 
3754 			continue;
3755 		}
3756 
3757 		if (0 == (applicationid = item_application->application_ref.applicationid))
3758 			applicationid = item_application->application_ref.application->applicationid;
3759 
3760 		if (0 == (itemid = item_application->item_ref.itemid))
3761 			itemid = item_application->item_ref.item->itemid;
3762 
3763 		item_application->itemappid = itemappid++;
3764 		zbx_db_insert_add_values(&db_insert, item_application->itemappid, applicationid, itemid);
3765 	}
3766 
3767 	if (0 != new_item_applications)
3768 	{
3769 		zbx_db_insert_execute(&db_insert);
3770 		zbx_db_insert_clean(&db_insert);
3771 	}
3772 
3773 	/* remove deprecated links */
3774 	if (0 != del_itemappids.values_num)
3775 	{
3776 		char	*sql = NULL;
3777 		size_t	sql_alloc = 0, sql_offset = 0;
3778 
3779 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from items_applications where");
3780 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemappid", del_itemappids.values,
3781 				del_itemappids.values_num);
3782 
3783 		DBexecute("%s", sql);
3784 
3785 		zbx_free(sql);
3786 	}
3787 
3788 	zbx_vector_uint64_destroy(&del_itemappids);
3789 out:
3790 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3791 }
3792 
3793 /******************************************************************************
3794  *                                                                            *
3795  * Function: lld_remove_lost_items                                            *
3796  *                                                                            *
3797  * Purpose: updates item_discovery.lastcheck and item_discovery.ts_delete     *
3798  *          fields; removes lost resources                                    *
3799  *                                                                            *
3800  ******************************************************************************/
lld_remove_lost_items(const zbx_vector_ptr_t * items,int lifetime,int lastcheck)3801 static void	lld_remove_lost_items(const zbx_vector_ptr_t *items, int lifetime, int lastcheck)
3802 {
3803 	const char			*__function_name = "lld_remove_lost_items";
3804 	char				*sql = NULL;
3805 	size_t				sql_alloc = 0, sql_offset = 0;
3806 	zbx_lld_item_t			*item;
3807 	zbx_vector_uint64_t		del_itemids, lc_itemids, ts_itemids;
3808 	zbx_vector_uint64_pair_t	discovery_itemts;
3809 	int				i;
3810 
3811 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3812 
3813 	if (0 == items->values_num)
3814 		goto out;
3815 
3816 	zbx_vector_uint64_create(&del_itemids);
3817 	zbx_vector_uint64_create(&lc_itemids);
3818 	zbx_vector_uint64_create(&ts_itemids);
3819 	zbx_vector_uint64_pair_create(&discovery_itemts);
3820 
3821 	for (i = 0; i < items->values_num; i++)
3822 	{
3823 		item = (zbx_lld_item_t *)items->values[i];
3824 
3825 		if (0 == item->itemid)
3826 			continue;
3827 
3828 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3829 		{
3830 			int	ts_delete = lld_end_of_life(item->lastcheck, lifetime);
3831 
3832 			if (lastcheck > ts_delete)
3833 			{
3834 				zbx_vector_uint64_append(&del_itemids, item->itemid);
3835 			}
3836 			else if (item->ts_delete != ts_delete)
3837 			{
3838 				zbx_uint64_pair_t	itemts;
3839 
3840 				itemts.first = item->itemid;
3841 				itemts.second = ts_delete;
3842 				zbx_vector_uint64_pair_append(&discovery_itemts, itemts);
3843 			}
3844 		}
3845 		else
3846 		{
3847 			zbx_vector_uint64_append(&lc_itemids, item->itemid);
3848 			if (0 != item->ts_delete)
3849 				zbx_vector_uint64_append(&ts_itemids, item->itemid);
3850 		}
3851 	}
3852 
3853 	if (0 == discovery_itemts.values_num && 0 == lc_itemids.values_num && 0 == ts_itemids.values_num &&
3854 			0 == del_itemids.values_num)
3855 	{
3856 		goto clean;
3857 	}
3858 
3859 	/* update item discovery table */
3860 
3861 	DBbegin();
3862 
3863 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3864 
3865 	for (i = 0; i < discovery_itemts.values_num; i++)
3866 	{
3867 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3868 				"update item_discovery"
3869 				" set ts_delete=%d"
3870 				" where itemid=" ZBX_FS_UI64 ";\n",
3871 				(int)discovery_itemts.values[i].second, discovery_itemts.values[i].first);
3872 
3873 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3874 	}
3875 
3876 	if (0 != lc_itemids.values_num)
3877 	{
3878 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update item_discovery set lastcheck=%d where",
3879 				lastcheck);
3880 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
3881 				lc_itemids.values, lc_itemids.values_num);
3882 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3883 
3884 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3885 	}
3886 
3887 	if (0 != ts_itemids.values_num)
3888 	{
3889 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update item_discovery set ts_delete=0 where");
3890 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
3891 				ts_itemids.values, ts_itemids.values_num);
3892 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3893 
3894 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3895 	}
3896 
3897 	DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3898 
3899 	if (16 < sql_offset)	/* in ORACLE always present begin..end; */
3900 		DBexecute("%s", sql);
3901 
3902 	zbx_free(sql);
3903 
3904 	/* remove 'lost' items */
3905 	if (0 != del_itemids.values_num)
3906 	{
3907 		zbx_vector_uint64_sort(&del_itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3908 		DBdelete_items(&del_itemids);
3909 	}
3910 
3911 	DBcommit();
3912 clean:
3913 	zbx_vector_uint64_pair_destroy(&discovery_itemts);
3914 	zbx_vector_uint64_destroy(&ts_itemids);
3915 	zbx_vector_uint64_destroy(&lc_itemids);
3916 	zbx_vector_uint64_destroy(&del_itemids);
3917 out:
3918 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3919 }
3920 
3921 /******************************************************************************
3922  *                                                                            *
3923  * Function: lld_remove_lost_applications                                     *
3924  *                                                                            *
3925  * Purpose: updates application_discovery lastcheck and ts_delete fields,     *
3926  *          removes lost resources                                            *
3927  *                                                                            *
3928  ******************************************************************************/
lld_remove_lost_applications(zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * applications,int lifetime,int lastcheck)3929 static void	lld_remove_lost_applications(zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *applications,
3930 		int lifetime, int lastcheck)
3931 {
3932 	const char			*__function_name = "lld_remove_lost_applications";
3933 	DB_RESULT			result;
3934 	DB_ROW				row;
3935 	char				*sql = NULL;
3936 	size_t				sql_alloc = 0, sql_offset = 0;
3937 	zbx_vector_uint64_t		del_applicationids, del_discoveryids, ts_discoveryids, lc_discoveryids;
3938 	zbx_vector_uint64_pair_t	discovery_applicationts;
3939 	int				i, index;
3940 	const zbx_lld_application_t	*application;
3941 	zbx_uint64_t			applicationid;
3942 
3943 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3944 
3945 	if (0 == applications->values_num)
3946 		goto out;
3947 
3948 	zbx_vector_uint64_create(&del_applicationids);
3949 	zbx_vector_uint64_create(&del_discoveryids);
3950 	zbx_vector_uint64_create(&ts_discoveryids);
3951 	zbx_vector_uint64_create(&lc_discoveryids);
3952 	zbx_vector_uint64_pair_create(&discovery_applicationts);
3953 
3954 	/* prepare application discovery update vector */
3955 	for (i = 0; i < applications->values_num; i++)
3956 	{
3957 		application = (const zbx_lld_application_t *)applications->values[i];
3958 
3959 		if (0 == application->applicationid)
3960 			continue;
3961 
3962 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
3963 		{
3964 			int	ts_delete = lld_end_of_life(application->lastcheck, lifetime);
3965 
3966 			if (lastcheck > ts_delete)
3967 			{
3968 				zbx_vector_uint64_append(&del_applicationids, application->applicationid);
3969 				zbx_vector_uint64_append(&del_discoveryids, application->application_discoveryid);
3970 			}
3971 			else if (application->ts_delete != ts_delete)
3972 			{
3973 				zbx_uint64_pair_t	applicationts;
3974 
3975 				applicationts.first = application->application_discoveryid;
3976 				applicationts.second = ts_delete;
3977 				zbx_vector_uint64_pair_append(&discovery_applicationts, applicationts);
3978 			}
3979 		}
3980 		else
3981 		{
3982 			zbx_vector_uint64_append(&lc_discoveryids, application->application_discoveryid);
3983 			if (0 != application->ts_delete)
3984 				zbx_vector_uint64_append(&ts_discoveryids, application->application_discoveryid);
3985 		}
3986 	}
3987 
3988 	/* check if the applications are really 'lost' (not discovered by other discovery rules) */
3989 	if (0 != del_applicationids.values_num)
3990 	{
3991 		zbx_vector_uint64_sort(&del_applicationids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3992 
3993 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3994 				"select ad.applicationid from application_discovery ad,application_prototype ap"
3995 				" where ad.application_prototypeid=ap.application_prototypeid"
3996 					" and ap.itemid<>" ZBX_FS_UI64
3997 					" and",
3998 				lld_ruleid);
3999 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ad.applicationid", del_applicationids.values,
4000 				del_applicationids.values_num);
4001 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by ad.applicationid desc");
4002 
4003 		result = DBselect("%s", sql);
4004 
4005 		sql_offset = 0;
4006 
4007 		while (NULL != (row = DBfetch(result)))
4008 		{
4009 			ZBX_STR2UINT64(applicationid, row[0]);
4010 
4011 			if (FAIL != (index = zbx_vector_uint64_bsearch(&del_applicationids, applicationid,
4012 					ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
4013 			{
4014 				zbx_vector_uint64_remove(&del_applicationids, index);
4015 			}
4016 		}
4017 
4018 		DBfree_result(result);
4019 	}
4020 
4021 	if (0 == discovery_applicationts.values_num && 0 == del_applicationids.values_num &&
4022 			0 == del_discoveryids.values_num && 0 == ts_discoveryids.values_num &&
4023 			0 == lc_discoveryids.values_num)
4024 	{
4025 		goto clean;
4026 	}
4027 
4028 	/* remove lost applications and update application discovery table */
4029 
4030 	DBbegin();
4031 
4032 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
4033 
4034 	for (i = 0; i < discovery_applicationts.values_num; i++)
4035 	{
4036 		zbx_uint64_pair_t	*applicationts = &(discovery_applicationts.values[i]);
4037 
4038 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4039 				"update application_discovery"
4040 				" set ts_delete=%d"
4041 				" where application_discoveryid=" ZBX_FS_UI64 ";\n",
4042 				(int)applicationts->second, applicationts->first);
4043 
4044 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4045 	}
4046 
4047 	if (0 != del_discoveryids.values_num)
4048 	{
4049 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from application_discovery where");
4050 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
4051 				del_discoveryids.values, del_discoveryids.values_num);
4052 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
4053 
4054 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4055 	}
4056 
4057 	if (0 != ts_discoveryids.values_num)
4058 	{
4059 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update application_discovery"
4060 				" set ts_delete=0 where");
4061 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
4062 				ts_discoveryids.values, ts_discoveryids.values_num);
4063 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
4064 
4065 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4066 	}
4067 
4068 	if (0 != lc_discoveryids.values_num)
4069 	{
4070 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update application_discovery"
4071 				" set lastcheck=%d where", lastcheck);
4072 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
4073 				lc_discoveryids.values, lc_discoveryids.values_num);
4074 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
4075 
4076 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4077 	}
4078 
4079 	if (0 != del_applicationids.values_num)
4080 	{
4081 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from applications where");
4082 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "applicationid", del_applicationids.values,
4083 				del_applicationids.values_num);
4084 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
4085 
4086 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4087 	}
4088 
4089 	DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
4090 
4091 	if (16 < sql_offset)	/* in ORACLE always present begin..end; */
4092 		DBexecute("%s", sql);
4093 
4094 	DBcommit();
4095 clean:
4096 	zbx_free(sql);
4097 
4098 	zbx_vector_uint64_pair_destroy(&discovery_applicationts);
4099 	zbx_vector_uint64_destroy(&lc_discoveryids);
4100 	zbx_vector_uint64_destroy(&ts_discoveryids);
4101 	zbx_vector_uint64_destroy(&del_discoveryids);
4102 	zbx_vector_uint64_destroy(&del_applicationids);
4103 out:
4104 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4105 }
4106 
lld_item_links_populate(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * lld_rows,zbx_hashset_t * items_index)4107 static void	lld_item_links_populate(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *lld_rows,
4108 		zbx_hashset_t *items_index)
4109 {
4110 	int				i, j;
4111 	zbx_lld_item_prototype_t	*item_prototype;
4112 	zbx_lld_item_index_t		*item_index, item_index_local;
4113 	zbx_lld_item_link_t		*item_link;
4114 
4115 	for (i = 0; i < item_prototypes->values_num; i++)
4116 	{
4117 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
4118 		item_index_local.parent_itemid = item_prototype->itemid;
4119 
4120 		for (j = 0; j < lld_rows->values_num; j++)
4121 		{
4122 			item_index_local.lld_row = (zbx_lld_row_t *)lld_rows->values[j];
4123 
4124 			if (NULL == (item_index = (zbx_lld_item_index_t *)zbx_hashset_search(items_index, &item_index_local)))
4125 				continue;
4126 
4127 			if (0 == (item_index->item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
4128 				continue;
4129 
4130 			item_link = (zbx_lld_item_link_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_link_t));
4131 
4132 			item_link->parent_itemid = item_index->item->parent_itemid;
4133 			item_link->itemid = item_index->item->itemid;
4134 
4135 			zbx_vector_ptr_append(&item_index_local.lld_row->item_links, item_link);
4136 		}
4137 	}
4138 }
4139 
lld_item_links_sort(zbx_vector_ptr_t * lld_rows)4140 void	lld_item_links_sort(zbx_vector_ptr_t *lld_rows)
4141 {
4142 	int	i;
4143 
4144 	for (i = 0; i < lld_rows->values_num; i++)
4145 	{
4146 		zbx_lld_row_t	*lld_row = (zbx_lld_row_t *)lld_rows->values[i];
4147 
4148 		zbx_vector_ptr_sort(&lld_row->item_links, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4149 	}
4150 }
4151 
4152 /******************************************************************************
4153  *                                                                            *
4154  * Function: lld_application_prototypes_get                                   *
4155  *                                                                            *
4156  * Purpose: gets the discovery rule application prototypes from database      *
4157  *                                                                            *
4158  * Parameters: lld_ruleid             - [IN] the discovery rule id            *
4159  *             application_prototypes - [OUT] the applications prototypes     *
4160  *                                            defined for the discovery rule, *
4161  *                                            sorted by prototype id          *
4162  *                                                                            *
4163  ******************************************************************************/
lld_application_prototypes_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * application_prototypes)4164 static void	lld_application_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *application_prototypes)
4165 {
4166 	const char			*__function_name = "lld_application_prototypes_get";
4167 	DB_RESULT			result;
4168 	DB_ROW				row;
4169 	zbx_lld_application_prototype_t	*application_prototype;
4170 
4171 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4172 
4173 	result = DBselect(
4174 			"select application_prototypeid,name"
4175 			" from application_prototype"
4176 			" where itemid=" ZBX_FS_UI64,
4177 			lld_ruleid);
4178 
4179 	while (NULL != (row = DBfetch(result)))
4180 	{
4181 		application_prototype = (zbx_lld_application_prototype_t *)zbx_malloc(NULL,
4182 				sizeof(zbx_lld_application_prototype_t));
4183 
4184 		ZBX_STR2UINT64(application_prototype->application_prototypeid, row[0]);
4185 		application_prototype->itemid = lld_ruleid;
4186 		application_prototype->name = zbx_strdup(NULL, row[1]);
4187 
4188 		zbx_vector_ptr_append(application_prototypes, application_prototype);
4189 	}
4190 	DBfree_result(result);
4191 
4192 	zbx_vector_ptr_sort(application_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4193 
4194 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d prototypes", __function_name, application_prototypes->values_num);
4195 }
4196 
4197 /******************************************************************************
4198  *                                                                            *
4199  * Function: lld_item_application_prototypes_get                              *
4200  *                                                                            *
4201  * Purpose: gets the discovery rule item-application link prototypes from     *
4202  *          database                                                          *
4203  *                                                                            *
4204  * Parameters: item_prototypes        - [IN/OUT] item prototypes              *
4205  *             application_prototypes - [IN] the application prototypes       *
4206  *                                           defined for the discovery rule   *
4207  *                                                                            *
4208  ******************************************************************************/
lld_item_application_prototypes_get(const zbx_vector_ptr_t * item_prototypes,const zbx_vector_ptr_t * application_prototypes)4209 static void	lld_item_application_prototypes_get(const zbx_vector_ptr_t *item_prototypes,
4210 		const zbx_vector_ptr_t *application_prototypes)
4211 {
4212 	const char			*__function_name = "lld_item_application_prototypes_get";
4213 	DB_RESULT			result;
4214 	DB_ROW				row;
4215 	int				i, index;
4216 	zbx_uint64_t			application_prototypeid, itemid;
4217 	zbx_vector_uint64_t		item_prototypeids;
4218 	char				*sql = NULL;
4219 	size_t				sql_alloc = 0, sql_offset = 0;
4220 	zbx_lld_item_application_ref_t	*item_application_prototype;
4221 	zbx_lld_item_prototype_t	*item_prototype;
4222 
4223 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4224 
4225 	zbx_vector_uint64_create(&item_prototypeids);
4226 
4227 	/* get item prototype links to application prototypes */
4228 
4229 	for (i = 0; i < item_prototypes->values_num; i++)
4230 	{
4231 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
4232 
4233 		zbx_vector_uint64_append(&item_prototypeids, item_prototype->itemid);
4234 	}
4235 
4236 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4237 			"select application_prototypeid,itemid"
4238 			" from item_application_prototype"
4239 			" where");
4240 
4241 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
4242 			item_prototypeids.values, item_prototypeids.values_num);
4243 
4244 	result = DBselect("%s", sql);
4245 
4246 	while (NULL != (row = DBfetch(result)))
4247 	{
4248 		ZBX_STR2UINT64(application_prototypeid, row[0]);
4249 
4250 		if (FAIL == (index = zbx_vector_ptr_search(application_prototypes, &application_prototypeid,
4251 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4252 		{
4253 			THIS_SHOULD_NEVER_HAPPEN;
4254 			continue;
4255 		}
4256 
4257 		item_application_prototype = (zbx_lld_item_application_ref_t *)zbx_malloc(NULL,
4258 				sizeof(zbx_lld_item_application_ref_t));
4259 
4260 		item_application_prototype->application_prototype = (zbx_lld_application_prototype_t *)application_prototypes->values[index];
4261 		item_application_prototype->applicationid = 0;
4262 
4263 		ZBX_STR2UINT64(itemid, row[1]);
4264 		index = zbx_vector_ptr_bsearch(item_prototypes, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4265 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
4266 
4267 		zbx_vector_ptr_append(&item_prototype->applications, item_application_prototype);
4268 	}
4269 	DBfree_result(result);
4270 
4271 	/* get item prototype links to real applications */
4272 
4273 	sql_offset = 0;
4274 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4275 			"select applicationid,itemid"
4276 			" from items_applications"
4277 			" where");
4278 
4279 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
4280 			item_prototypeids.values, item_prototypeids.values_num);
4281 
4282 	result = DBselect("%s", sql);
4283 
4284 	while (NULL != (row = DBfetch(result)))
4285 	{
4286 		item_application_prototype = (zbx_lld_item_application_ref_t *)zbx_malloc(NULL,
4287 				sizeof(zbx_lld_item_application_ref_t));
4288 
4289 		item_application_prototype->application_prototype = NULL;
4290 		ZBX_STR2UINT64(item_application_prototype->applicationid, row[0]);
4291 
4292 		ZBX_STR2UINT64(itemid, row[1]);
4293 		index = zbx_vector_ptr_bsearch(item_prototypes, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4294 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
4295 
4296 		zbx_vector_ptr_append(&item_prototype->applications, item_application_prototype);
4297 	}
4298 	DBfree_result(result);
4299 
4300 	zbx_free(sql);
4301 	zbx_vector_uint64_destroy(&item_prototypeids);
4302 
4303 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4304 }
4305 
4306 /******************************************************************************
4307  *                                                                            *
4308  * Function: lld_applications_get                                             *
4309  *                                                                            *
4310  * Purpose: gets applications previously discovered by the discovery rule     *
4311  *                                                                            *
4312  * Parameters: lld_ruleid   - [IN] the discovery rule id                      *
4313  *             applications - [OUT] the applications                          *
4314  *                                                                            *
4315  ******************************************************************************/
lld_applications_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * applications)4316 static void	lld_applications_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *applications)
4317 {
4318 	const char		*__function_name = "lld_applications_get";
4319 	DB_RESULT		result;
4320 	DB_ROW			row;
4321 	zbx_lld_application_t	*application;
4322 
4323 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4324 
4325 	result = DBselect(
4326 			"select a.applicationid,a.name,ap.application_prototypeid,ad.lastcheck,ad.ts_delete,ad.name,"
4327 				"ad.application_discoveryid"
4328 			" from applications a,application_discovery ad,application_prototype ap"
4329 			" where ap.itemid=" ZBX_FS_UI64
4330 				" and ad.application_prototypeid=ap.application_prototypeid"
4331 				" and a.applicationid=ad.applicationid",
4332 			lld_ruleid);
4333 
4334 	while (NULL != (row = DBfetch(result)))
4335 	{
4336 		application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
4337 
4338 		ZBX_STR2UINT64(application->applicationid, row[0]);
4339 		ZBX_STR2UINT64(application->application_prototypeid, row[2]);
4340 		ZBX_STR2UINT64(application->application_discoveryid, row[6]);
4341 		application->name = zbx_strdup(NULL, row[1]);
4342 		application->lastcheck = atoi(row[3]);
4343 		application->ts_delete = atoi(row[4]);
4344 		application->name_proto = zbx_strdup(NULL, row[5]);
4345 		application->name_orig = NULL;
4346 		application->flags = ZBX_FLAG_LLD_APPLICATION_UNSET;
4347 		application->lld_row = NULL;
4348 
4349 		zbx_vector_ptr_append(applications, application);
4350 	}
4351 	DBfree_result(result);
4352 
4353 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d applications", __function_name, applications->values_num);
4354 }
4355 
4356 /******************************************************************************
4357  *                                                                            *
4358  * Function: lld_application_make                                             *
4359  *                                                                            *
4360  * Purpose: create a new application or mark an existing application as       *
4361  *          discovered based on prototype and lld row                         *
4362  *                                                                            *
4363  * Parameters: application_prototype - [IN] the application prototype         *
4364  *             lld_row               - [IN] the lld row                       *
4365  *             applications          - [IN/OUT] the applications              *
4366  *             applications_index    - [IN/OUT] the application index by      *
4367  *                                              prototype id and lld row      *
4368  *                                                                            *
4369  ******************************************************************************/
lld_application_make(const zbx_lld_application_prototype_t * application_prototype,const zbx_lld_row_t * lld_row,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index)4370 static void	lld_application_make(const zbx_lld_application_prototype_t *application_prototype,
4371 		const zbx_lld_row_t *lld_row, zbx_vector_ptr_t *applications, zbx_hashset_t *applications_index)
4372 {
4373 	const char			*__function_name = "lld_application_make";
4374 	zbx_lld_application_t		*application;
4375 	zbx_lld_application_index_t	*application_index, application_index_local;
4376 	struct zbx_json_parse		*jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
4377 	char				*buffer = NULL;
4378 
4379 	zabbix_log(LOG_LEVEL_DEBUG, "In %s(), proto %s", __function_name, application_prototype->name);
4380 
4381 	application_index_local.application_prototypeid = application_prototype->application_prototypeid;
4382 	application_index_local.lld_row = lld_row;
4383 
4384 	if (NULL == (application_index = (zbx_lld_application_index_t *)zbx_hashset_search(applications_index, &application_index_local)))
4385 	{
4386 		application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
4387 		application->applicationid = 0;
4388 		application->application_prototypeid = application_prototype->application_prototypeid;
4389 		application->application_discoveryid = 0;
4390 		application->ts_delete = 0;
4391 
4392 		application->name = zbx_strdup(NULL, application_prototype->name);
4393 		substitute_lld_macros(&application->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
4394 		zbx_lrtrim(application->name, ZBX_WHITESPACE);
4395 
4396 		application->name_proto = zbx_strdup(NULL, application_prototype->name);
4397 		application->name_orig = NULL;
4398 		application->flags = ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY;
4399 		application->lld_row = lld_row;
4400 
4401 		zbx_vector_ptr_append(applications, application);
4402 
4403 		application_index_local.application = application;
4404 		zbx_hashset_insert(applications_index, &application_index_local, sizeof(zbx_lld_application_index_t));
4405 
4406 		zabbix_log(LOG_LEVEL_TRACE, "%s(): created new application, proto %s, name %s", __function_name,
4407 				application_prototype->name, application->name);
4408 	}
4409 	else
4410 	{
4411 		application = application_index->application;
4412 
4413 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
4414 		{
4415 			buffer = zbx_strdup(NULL, application_prototype->name);
4416 			substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
4417 			zbx_lrtrim(buffer, ZBX_WHITESPACE);
4418 
4419 			if (0 != strcmp(application->name, buffer))
4420 			{
4421 				application->name_orig = application->name;
4422 				application->name = buffer;
4423 				application->flags |= ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME;
4424 				zabbix_log(LOG_LEVEL_TRACE, "%s(): updated application name to %s", __function_name,
4425 						application->name);
4426 			}
4427 			else
4428 				zbx_free(buffer);
4429 		}
4430 	}
4431 
4432 	application->flags |= ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
4433 
4434 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4435 }
4436 
4437 /******************************************************************************
4438  *                                                                            *
4439  * Function: lld_applications_make                                            *
4440  *                                                                            *
4441  * Purpose: makes new applications and marks old applications as discovered   *
4442  *          based on application prototypes and lld rows                      *
4443  *                                                                            *
4444  * Parameters: application_prototypes - [IN] the application prototypes       *
4445  *             lld_rows               - [IN] the lld rows                     *
4446  *             applications           - [IN/OUT] the applications             *
4447  *             applications_index     - [OUT] the application index by        *
4448  *                                            prototype id and lld row        *
4449  *                                                                            *
4450  ******************************************************************************/
lld_applications_make(const zbx_vector_ptr_t * application_prototypes,const zbx_vector_ptr_t * lld_rows,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index)4451 static void	lld_applications_make(const zbx_vector_ptr_t *application_prototypes,
4452 		const zbx_vector_ptr_t *lld_rows, zbx_vector_ptr_t *applications, zbx_hashset_t *applications_index)
4453 {
4454 	const char			*__function_name = "lld_applications_make";
4455 	int				i, j;
4456 	zbx_lld_application_t		*application;
4457 	zbx_lld_row_t			*lld_row;
4458 	zbx_lld_application_index_t	application_index_local;
4459 	char				*buffer = NULL;
4460 
4461 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4462 
4463 	/* index existing applications */
4464 
4465 	for (i = 0; i < applications->values_num; i++)
4466 	{
4467 		application = (zbx_lld_application_t *)applications->values[i];
4468 
4469 		for (j = 0; j < lld_rows->values_num; j++)
4470 		{
4471 			lld_row = (zbx_lld_row_t *)lld_rows->values[j];
4472 
4473 			buffer = zbx_strdup(buffer, application->name_proto);
4474 			substitute_lld_macros(&buffer, &lld_row->jp_row, ZBX_MACRO_ANY, NULL, 0);
4475 			zbx_lrtrim(buffer, ZBX_WHITESPACE);
4476 
4477 			if (0 == strcmp(application->name, buffer))
4478 			{
4479 				application_index_local.application_prototypeid = application->application_prototypeid;
4480 				application_index_local.lld_row = lld_row;
4481 				application_index_local.application = application;
4482 				zbx_hashset_insert(applications_index, &application_index_local,
4483 						sizeof(application_index_local));
4484 
4485 				application->lld_row = lld_row;
4486 			}
4487 		}
4488 	}
4489 
4490 	zbx_free(buffer);
4491 
4492 	/* make the applications */
4493 	for (i = 0; i < application_prototypes->values_num; i++)
4494 	{
4495 		for (j = 0; j < lld_rows->values_num; j++)
4496 		{
4497 			lld_application_make((zbx_lld_application_prototype_t *)application_prototypes->values[i],
4498 					(zbx_lld_row_t *)lld_rows->values[j], applications, applications_index);
4499 		}
4500 	}
4501 
4502 	zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4503 
4504 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d applications", __function_name, applications->values_num);
4505 }
4506 
4507 /******************************************************************************
4508  *                                                                            *
4509  * Function: lld_applications_validate                                        *
4510  *                                                                            *
4511  * Purpose: validates the discovered and renamed applications                 *
4512  *                                                                            *
4513  * Parameters: hostid             - [IN] host id                              *
4514  *             lld_ruleid         - [IN] the discovery rule id                *
4515  *             applications       - [IN/OUT] the applications                 *
4516  *             applications_index - [OUT] the application index by            *
4517  *                                        prototype id and lld row            *
4518  *             error              - [IN/OUT] the lld error message            *
4519  *                                                                            *
4520  ******************************************************************************/
lld_applications_validate(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index,char ** error)4521 static void	lld_applications_validate(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *applications,
4522 		zbx_hashset_t *applications_index, char **error)
4523 {
4524 	const char			*__function_name = "lld_applications_validate";
4525 	int				i, j, index;
4526 	DB_RESULT			result;
4527 	DB_ROW				row;
4528 	zbx_lld_application_t		*application, *new_application, application_local;
4529 	char				*sql = NULL;
4530 	size_t				sql_alloc = 0, sql_offset = 0;
4531 	zbx_vector_str_t		names_new, names_old;
4532 	zbx_lld_application_index_t	*application_index, application_index_local;
4533 
4534 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4535 
4536 	if (0 == applications->values_num)
4537 		goto out;
4538 
4539 	zbx_vector_str_create(&names_new);
4540 	zbx_vector_str_create(&names_old);
4541 
4542 	/* check for conflicting application names in the discovered applications */
4543 
4544 	for (i = 0; i < applications->values_num; i++)
4545 	{
4546 		application = (zbx_lld_application_t *)applications->values[i];
4547 
4548 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
4549 			continue;
4550 
4551 		if (0 != application->applicationid && 0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
4552 			continue;
4553 
4554 		/* iterate in reverse order so existing applications would have more priority */
4555 		/* than new applications which have 0 applicationid and therefore are located */
4556 		/* at the beginning of applications vector which is sorted by applicationid   */
4557 		for (j = applications->values_num - 1; j > i; j--)
4558 		{
4559 			zbx_lld_application_t	*application_compare = (zbx_lld_application_t *)applications->values[j];
4560 
4561 			if (0 != strcmp(application->name, application_compare->name))
4562 				continue;
4563 
4564 			/* Applications with matching names are validated depending on their prototypes. */
4565 			/* If they are discovered by different prototypes we must fail with appropriate  */
4566 			/* lld error.                                                                    */
4567 			/* Otherwise we 'merge' application by updating index of the validated           */
4568 			/* validated application to point at the application with the same name.         */
4569 			/* In both cases the validated application is flagged as non-discovered.         */
4570 			application->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
4571 
4572 			/* fail if application has different prototype */
4573 			if (application->application_prototypeid != application_compare->application_prototypeid)
4574 			{
4575 				*error = zbx_strdcatf(*error, "Cannot %s application:"
4576 						" application with the same name \"%s\" already exists.\n",
4577 						(0 != application->applicationid ? "update" : "create"),
4578 						application->name);
4579 
4580 				break;
4581 			}
4582 
4583 			/* update application index to use the matching application */
4584 
4585 			application_index_local.application_prototypeid = application->application_prototypeid;
4586 			application_index_local.lld_row = application->lld_row;
4587 
4588 			if (NULL == (application_index = (zbx_lld_application_index_t *)zbx_hashset_search(applications_index,
4589 					&application_index_local)))
4590 			{
4591 				THIS_SHOULD_NEVER_HAPPEN;
4592 				break;
4593 			}
4594 
4595 			application_index->application = application_compare;
4596 			break;
4597 		}
4598 
4599 		/* Prepare name lists to resolve naming conflicts with applications */
4600 		/* discovered by other discovery rules:                             */
4601 		/*   names_new - to check if discovered/renamed application names   */
4602 		/*               don't match existing applications discovered by    */
4603 		/*               other discovery rules                              */
4604 		/*   names_old - to check if renamed applications were also         */
4605 		/*               discovered by other discovery rules                */
4606 		if (i == j)
4607 		{
4608 			zbx_vector_str_append(&names_new, application->name);
4609 
4610 			if (NULL != application->name_orig)
4611 				zbx_vector_str_append(&names_old, application->name_orig);
4612 		}
4613 	}
4614 
4615 	/* validate new/renamed application names against applications discovered */
4616 	/* by other discovery rules                                               */
4617 
4618 	if (0 != names_new.values_num)
4619 	{
4620 		zbx_vector_str_sort(&names_new, ZBX_DEFAULT_STR_COMPARE_FUNC);
4621 
4622 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4623 				"select applicationid,name,flags"
4624 				" from applications"
4625 				" where hostid=" ZBX_FS_UI64
4626 					" and",
4627 				hostid);
4628 		DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
4629 				(const char **)names_new.values, names_new.values_num);
4630 
4631 		result = DBselect("%s", sql);
4632 
4633 		application_local.flags = ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
4634 
4635 		while (NULL != (row = DBfetch(result)))
4636 		{
4637 			application_local.name = row[1];
4638 
4639 			if (FAIL == (index = zbx_vector_ptr_search(applications, &application_local,
4640 					lld_application_compare_name)))
4641 			{
4642 				THIS_SHOULD_NEVER_HAPPEN;
4643 				continue;
4644 			}
4645 
4646 			application = (zbx_lld_application_t *)applications->values[index];
4647 
4648 			/* only discovered applications can be 'shared' between discovery rules */
4649 			if (ZBX_FLAG_DISCOVERY_CREATED != atoi(row[2]))
4650 			{
4651 				/* conflicting application name, reset discovery flags */
4652 				application->flags = ZBX_FLAG_LLD_APPLICATION_UNSET;
4653 
4654 				*error = zbx_strdcatf(*error, "Cannot create application:"
4655 						" non-discovered application"
4656 						" with the same name \"%s\" already exists.\n",
4657 						application->name);
4658 
4659 				continue;
4660 			}
4661 
4662 			if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
4663 			{
4664 				/* During discovery process the application was renamed to an */
4665 				/* application already discovered by another discovery rule.  */
4666 				/* In this case we must delete the old application and relink */
4667 				/* its items to the application we have found.                */
4668 
4669 				/* create a pseudo application to remove the renamed application */
4670 
4671 				new_application = (zbx_lld_application_t *)zbx_malloc(NULL,
4672 						sizeof(zbx_lld_application_t));
4673 
4674 				memset(new_application, 0, sizeof(zbx_lld_application_t));
4675 				new_application->applicationid = application->applicationid;
4676 				new_application->flags = ZBX_FLAG_LLD_APPLICATION_REMOVE;
4677 
4678 				zbx_vector_ptr_append(applications, new_application);
4679 
4680 				/* update application flags so that instead of renaming it a new */
4681 				/* discovery record is created                                   */
4682 
4683 				application->application_discoveryid = 0;
4684 				application->flags &= ~ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME;
4685 				application->flags |= ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY;
4686 			}
4687 
4688 			/* reuse application created by another discovery rule */
4689 			ZBX_STR2UINT64(application->applicationid, row[0]);
4690 		}
4691 		DBfree_result(result);
4692 	}
4693 
4694 	/* if an application shared with other discovery rule has been renamed we must */
4695 	/* create a new application with the new name instead of renaming the old one  */
4696 
4697 	if (0 != names_old.values_num)
4698 	{
4699 		sql_offset = 0;
4700 
4701 		zbx_vector_str_sort(&names_old, ZBX_DEFAULT_STR_COMPARE_FUNC);
4702 
4703 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4704 				"select a.name"
4705 				" from applications a,application_discovery ad,application_prototype ap"
4706 				" where a.applicationid=ad.applicationid"
4707 					" and ad.application_prototypeid=ap.application_prototypeid"
4708 					" and a.hostid=" ZBX_FS_UI64
4709 					" and ap.itemid<>" ZBX_FS_UI64
4710 					" and",
4711 				hostid, lld_ruleid);
4712 		DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "a.name",
4713 				(const char **)names_old.values, names_old.values_num);
4714 
4715 		result = DBselect("%s", sql);
4716 
4717 		application_local.flags = ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
4718 
4719 		while (NULL != (row = DBfetch(result)))
4720 		{
4721 			application_local.name_orig = row[0];
4722 
4723 			if (FAIL == (index = zbx_vector_ptr_search(applications, &application_local,
4724 					lld_application_compare_name_orig)))
4725 			{
4726 				THIS_SHOULD_NEVER_HAPPEN;
4727 				continue;
4728 			}
4729 
4730 			application = (zbx_lld_application_t *)applications->values[index];
4731 
4732 			/* add a pseudo application to remove the application discovery record */
4733 			/* of the shared application and current discovery rule                */
4734 			new_application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
4735 			memset(new_application, 0, sizeof(zbx_lld_application_t));
4736 			new_application->applicationid = application->applicationid;
4737 			new_application->application_prototypeid = application->application_prototypeid;
4738 			new_application->application_discoveryid = application->application_discoveryid;
4739 			new_application->flags = ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY;
4740 			zbx_vector_ptr_append(applications, new_application);
4741 
4742 			/* reset applicationid, application_discoveryid and flags             */
4743 			/* so a new application is created instead of renaming the shared one */
4744 			application->applicationid = 0;
4745 			application->application_discoveryid = 0;
4746 			application->flags = ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY |
4747 					ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
4748 		}
4749 		DBfree_result(result);
4750 	}
4751 
4752 	zbx_vector_str_destroy(&names_old);
4753 	zbx_vector_str_destroy(&names_new);
4754 
4755 	zbx_free(sql);
4756 
4757 	zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4758 out:
4759 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4760 }
4761 
4762 /******************************************************************************
4763  *                                                                            *
4764  * Function: lld_items_applications_get                                       *
4765  *                                                                            *
4766  * Purpose: gets item-application links for the lld rule                      *
4767  *                                                                            *
4768  * Parameters: lld_rule           - [IN] the lld rule                         *
4769  *             items_applications - [OUT] the item-application links          *
4770  *                                                                            *
4771  ******************************************************************************/
lld_items_applications_get(zbx_uint64_t lld_ruleid,zbx_hashset_t * items_applications)4772 static void	lld_items_applications_get(zbx_uint64_t lld_ruleid, zbx_hashset_t *items_applications)
4773 {
4774 	const char			*__function_name = "lld_items_applications_get";
4775 	DB_RESULT			result;
4776 	DB_ROW				row;
4777 	zbx_lld_item_application_t	item_application;
4778 
4779 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4780 
4781 	result = DBselect(
4782 			"select ia.itemappid,ia.itemid,ia.applicationid"
4783 			" from items_applications ia,item_discovery id1,item_discovery id2"
4784 			" where id1.itemid=ia.itemid"
4785 				" and id1.parent_itemid=id2.itemid"
4786 				" and id2.parent_itemid=" ZBX_FS_UI64,
4787 			lld_ruleid);
4788 
4789 	item_application.application_ref.application = NULL;
4790 	item_application.item_ref.item = NULL;
4791 
4792 	while (NULL != (row = DBfetch(result)))
4793 	{
4794 		ZBX_STR2UINT64(item_application.itemappid, row[0]);
4795 		ZBX_STR2UINT64(item_application.item_ref.itemid, row[1]);
4796 		ZBX_STR2UINT64(item_application.application_ref.applicationid, row[2]);
4797 		item_application.flags = ZBX_FLAG_LLD_ITEM_APPLICATION_UNSET;
4798 
4799 		zbx_hashset_insert(items_applications, &item_application, sizeof(zbx_lld_item_application_t));
4800 	}
4801 	DBfree_result(result);
4802 
4803 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d links", __function_name, items_applications->num_data);
4804 }
4805 
4806 /******************************************************************************
4807  *                                                                            *
4808  * Function: lld_items_applications_make                                      *
4809  *                                                                            *
4810  * Purpose: makes new item-application links and marks existing links as      *
4811  *          discovered based on item_prototypes applications links            *
4812  *                                                                            *
4813  * Parameters: item_prototypes    - [IN] the item prototypes                  *
4814  *             items              - [IN] the items                            *
4815  *             applications_index - [IN] the application index by             *
4816  *                                       prototype id and lld row             *
4817  *             items_applications - [IN/OUT] the item-application links       *
4818  *                                                                            *
4819  ******************************************************************************/
lld_items_applications_make(const zbx_vector_ptr_t * item_prototypes,const zbx_vector_ptr_t * items,zbx_hashset_t * applications_index,zbx_hashset_t * items_applications)4820 static void	lld_items_applications_make(const zbx_vector_ptr_t *item_prototypes, const zbx_vector_ptr_t *items,
4821 		zbx_hashset_t *applications_index, zbx_hashset_t *items_applications)
4822 {
4823 	const char			*__function_name = "lld_items_applications_make";
4824 	int				i, j, index;
4825 	zbx_lld_item_application_t	*item_application, item_application_local;
4826 	zbx_lld_application_t		*application;
4827 	zbx_lld_item_prototype_t	*item_prototype;
4828 	zbx_lld_item_t			*item;
4829 	zbx_lld_item_application_ref_t	*itemapp_prototype;
4830 	zbx_lld_application_index_t	*application_index, application_index_local;
4831 
4832 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4833 
4834 	item_application_local.itemappid = 0;
4835 	item_application_local.flags = ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED;
4836 
4837 	for (i = 0; i < items->values_num; i++)
4838 	{
4839 		item = (zbx_lld_item_t *)items->values[i];
4840 
4841 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
4842 			continue;
4843 
4844 		/* if item is discovered its prototype must be in item_prototypes vector */
4845 		index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
4846 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4847 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
4848 
4849 		application_index_local.lld_row = item->lld_row;
4850 
4851 		if (0 == (item_application_local.item_ref.itemid = item->itemid))
4852 			item_application_local.item_ref.item = item;
4853 		else
4854 			item_application_local.item_ref.item = NULL;
4855 
4856 		for (j = 0; j < item_prototype->applications.values_num; j++)
4857 		{
4858 			itemapp_prototype = (zbx_lld_item_application_ref_t *)item_prototype->applications.values[j];
4859 
4860 			if (NULL != itemapp_prototype->application_prototype)
4861 			{
4862 				application_index_local.application_prototypeid =
4863 						itemapp_prototype->application_prototype->application_prototypeid;
4864 
4865 				if (NULL == (application_index = (zbx_lld_application_index_t *)zbx_hashset_search(applications_index,
4866 						&application_index_local)))
4867 				{
4868 					continue;
4869 				}
4870 
4871 				application = application_index->application;
4872 
4873 				if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
4874 					continue;
4875 
4876 				if (0 == (item_application_local.application_ref.applicationid =
4877 						application->applicationid))
4878 				{
4879 					item_application_local.application_ref.application = application;
4880 				}
4881 				else
4882 					item_application_local.application_ref.application = NULL;
4883 			}
4884 			else
4885 			{
4886 				item_application_local.application_ref.application = NULL;
4887 				item_application_local.application_ref.applicationid = itemapp_prototype->applicationid;
4888 			}
4889 
4890 			if (NULL == (item_application = (zbx_lld_item_application_t *)zbx_hashset_search(items_applications,
4891 					&item_application_local)))
4892 			{
4893 				item_application = (zbx_lld_item_application_t *)zbx_hashset_insert(items_applications, &item_application_local,
4894 						sizeof(zbx_lld_item_application_t));
4895 			}
4896 
4897 			item_application->flags = ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED;
4898 		}
4899 	}
4900 
4901 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d links", __function_name, items_applications->num_data);
4902 }
4903 
4904 /******************************************************************************
4905  *                                                                            *
4906  * Function: lld_item_prototypes_get                                          *
4907  *                                                                            *
4908  * Purpose: load discovery rule item prototypes                               *
4909  *                                                                            *
4910  * Parameters: lld_ruleid      - [IN] the discovery rule id                   *
4911  *             item_prototypes - [OUT] the item prototypes                    *
4912  *                                                                            *
4913  ******************************************************************************/
lld_item_prototypes_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * item_prototypes)4914 static void	lld_item_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *item_prototypes)
4915 {
4916 	const char			*__function_name = "lld_item_prototypes_get";
4917 	DB_RESULT			result;
4918 	DB_ROW				row;
4919 	zbx_lld_item_prototype_t	*item_prototype;
4920 	zbx_lld_item_preproc_t		*preproc_op;
4921 	zbx_uint64_t			itemid;
4922 	int				index, i;
4923 
4924 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4925 
4926 	result = DBselect(
4927 			"select i.itemid,i.name,i.key_,i.type,i.value_type,i.delay,"
4928 				"i.history,i.trends,i.status,i.trapper_hosts,i.units,i.formula,"
4929 				"i.logtimefmt,i.valuemapid,i.params,i.ipmi_sensor,i.snmp_community,i.snmp_oid,"
4930 				"i.port,i.snmpv3_securityname,i.snmpv3_securitylevel,i.snmpv3_authprotocol,"
4931 				"i.snmpv3_authpassphrase,i.snmpv3_privprotocol,i.snmpv3_privpassphrase,i.authtype,"
4932 				"i.username,i.password,i.publickey,i.privatekey,i.description,i.interfaceid,"
4933 				"i.snmpv3_contextname,i.jmx_endpoint,i.master_itemid,i.timeout,i.url,i.query_fields,"
4934 				"i.posts,i.status_codes,i.follow_redirects,i.post_type,i.http_proxy,i.headers,"
4935 				"i.retrieve_mode,i.request_method,i.output_format,i.ssl_cert_file,i.ssl_key_file,"
4936 				"i.ssl_key_password,i.verify_peer,i.verify_host,i.allow_traps"
4937 			" from items i,item_discovery id"
4938 			" where i.itemid=id.itemid"
4939 				" and id.parent_itemid=" ZBX_FS_UI64,
4940 			lld_ruleid);
4941 
4942 	while (NULL != (row = DBfetch(result)))
4943 	{
4944 		item_prototype = (zbx_lld_item_prototype_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_prototype_t));
4945 
4946 		ZBX_STR2UINT64(item_prototype->itemid, row[0]);
4947 		item_prototype->name = zbx_strdup(NULL, row[1]);
4948 		item_prototype->key = zbx_strdup(NULL, row[2]);
4949 		ZBX_STR2UCHAR(item_prototype->type, row[3]);
4950 		ZBX_STR2UCHAR(item_prototype->value_type, row[4]);
4951 		item_prototype->delay = zbx_strdup(NULL, row[5]);
4952 		item_prototype->history = zbx_strdup(NULL, row[6]);
4953 		item_prototype->trends = zbx_strdup(NULL, row[7]);
4954 		ZBX_STR2UCHAR(item_prototype->status, row[8]);
4955 		item_prototype->trapper_hosts = zbx_strdup(NULL, row[9]);
4956 		item_prototype->units = zbx_strdup(NULL, row[10]);
4957 		item_prototype->formula = zbx_strdup(NULL, row[11]);
4958 		item_prototype->logtimefmt = zbx_strdup(NULL, row[12]);
4959 		ZBX_DBROW2UINT64(item_prototype->valuemapid, row[13]);
4960 		item_prototype->params = zbx_strdup(NULL, row[14]);
4961 		item_prototype->ipmi_sensor = zbx_strdup(NULL, row[15]);
4962 		item_prototype->snmp_community = zbx_strdup(NULL, row[16]);
4963 		item_prototype->snmp_oid = zbx_strdup(NULL, row[17]);
4964 		item_prototype->port = zbx_strdup(NULL, row[18]);
4965 		item_prototype->snmpv3_securityname = zbx_strdup(NULL, row[19]);
4966 		ZBX_STR2UCHAR(item_prototype->snmpv3_securitylevel, row[20]);
4967 		ZBX_STR2UCHAR(item_prototype->snmpv3_authprotocol, row[21]);
4968 		item_prototype->snmpv3_authpassphrase = zbx_strdup(NULL, row[22]);
4969 		ZBX_STR2UCHAR(item_prototype->snmpv3_privprotocol, row[23]);
4970 		item_prototype->snmpv3_privpassphrase = zbx_strdup(NULL, row[24]);
4971 		ZBX_STR2UCHAR(item_prototype->authtype, row[25]);
4972 		item_prototype->username = zbx_strdup(NULL, row[26]);
4973 		item_prototype->password = zbx_strdup(NULL, row[27]);
4974 		item_prototype->publickey = zbx_strdup(NULL, row[28]);
4975 		item_prototype->privatekey = zbx_strdup(NULL, row[29]);
4976 		item_prototype->description = zbx_strdup(NULL, row[30]);
4977 		ZBX_DBROW2UINT64(item_prototype->interfaceid, row[31]);
4978 		item_prototype->snmpv3_contextname = zbx_strdup(NULL, row[32]);
4979 		item_prototype->jmx_endpoint = zbx_strdup(NULL, row[33]);
4980 		ZBX_DBROW2UINT64(item_prototype->master_itemid, row[34]);
4981 
4982 		item_prototype->timeout = zbx_strdup(NULL, row[35]);
4983 		item_prototype->url = zbx_strdup(NULL, row[36]);
4984 		item_prototype->query_fields = zbx_strdup(NULL, row[37]);
4985 		item_prototype->posts = zbx_strdup(NULL, row[38]);
4986 		item_prototype->status_codes = zbx_strdup(NULL, row[39]);
4987 		ZBX_STR2UCHAR(item_prototype->follow_redirects, row[40]);
4988 		ZBX_STR2UCHAR(item_prototype->post_type, row[41]);
4989 		item_prototype->http_proxy = zbx_strdup(NULL, row[42]);
4990 		item_prototype->headers = zbx_strdup(NULL, row[43]);
4991 		ZBX_STR2UCHAR(item_prototype->retrieve_mode, row[44]);
4992 		ZBX_STR2UCHAR(item_prototype->request_method, row[45]);
4993 		ZBX_STR2UCHAR(item_prototype->output_format, row[46]);
4994 		item_prototype->ssl_cert_file = zbx_strdup(NULL, row[47]);
4995 		item_prototype->ssl_key_file = zbx_strdup(NULL, row[48]);
4996 		item_prototype->ssl_key_password = zbx_strdup(NULL, row[49]);
4997 		ZBX_STR2UCHAR(item_prototype->verify_peer, row[50]);
4998 		ZBX_STR2UCHAR(item_prototype->verify_host, row[51]);
4999 		ZBX_STR2UCHAR(item_prototype->allow_traps, row[52]);
5000 
5001 		zbx_vector_ptr_create(&item_prototype->lld_rows);
5002 		zbx_vector_ptr_create(&item_prototype->applications);
5003 		zbx_vector_ptr_create(&item_prototype->preproc_ops);
5004 
5005 		zbx_vector_ptr_append(item_prototypes, item_prototype);
5006 	}
5007 	DBfree_result(result);
5008 
5009 	zbx_vector_ptr_sort(item_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
5010 
5011 	if (0 == item_prototypes->values_num)
5012 		goto out;
5013 
5014 	/* get item prototype preprocessing options */
5015 
5016 	result = DBselect(
5017 			"select ip.itemid,ip.step,ip.type,ip.params from item_preproc ip,item_discovery id"
5018 			" where ip.itemid=id.itemid"
5019 				" and id.parent_itemid=" ZBX_FS_UI64,
5020 			lld_ruleid);
5021 
5022 	while (NULL != (row = DBfetch(result)))
5023 	{
5024 		ZBX_STR2UINT64(itemid, row[0]);
5025 
5026 		if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &itemid,
5027 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
5028 		{
5029 			THIS_SHOULD_NEVER_HAPPEN;
5030 			continue;
5031 		}
5032 
5033 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
5034 
5035 		preproc_op = (zbx_lld_item_preproc_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_preproc_t));
5036 		preproc_op->step = atoi(row[1]);
5037 		preproc_op->type = atoi(row[2]);
5038 		preproc_op->params = zbx_strdup(NULL, row[3]);
5039 		zbx_vector_ptr_append(&item_prototype->preproc_ops, preproc_op);
5040 	}
5041 	DBfree_result(result);
5042 
5043 	for (i = 0; i < item_prototypes->values_num; i++)
5044 	{
5045 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
5046 		zbx_vector_ptr_sort(&item_prototype->preproc_ops, lld_item_preproc_sort_by_step);
5047 	}
5048 
5049 out:
5050 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d prototypes", __function_name, item_prototypes->values_num);
5051 }
5052 
5053 /******************************************************************************
5054  *                                                                            *
5055  * Function: lld_link_dependent_items                                         *
5056  *                                                                            *
5057  * Purpose: create dependent item index in master item data                   *
5058  *                                                                            *
5059  * Parameters: items       - [IN/OUT] the lld items                           *
5060  *             items_index - [IN] lld item index                              *
5061  *                                                                            *
5062  ******************************************************************************/
lld_link_dependent_items(zbx_vector_ptr_t * items,zbx_hashset_t * items_index)5063 static void	lld_link_dependent_items(zbx_vector_ptr_t *items, zbx_hashset_t *items_index)
5064 {
5065 	const char		*__function_name = "lld_link_dependent_items";
5066 	zbx_lld_item_t		*item, *master;
5067 	zbx_lld_item_index_t	*item_index, item_index_local;
5068 	int			i;
5069 
5070 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
5071 
5072 	for (i = items->values_num - 1; i >= 0; i--)
5073 	{
5074 		item = (zbx_lld_item_t *)items->values[i];
5075 		/* only discovered dependent items should be linked */
5076 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED) || 0 == item->master_itemid)
5077 			continue;
5078 
5079 		item_index_local.parent_itemid = item->master_itemid;
5080 		item_index_local.lld_row = (zbx_lld_row_t *)item->lld_row;
5081 
5082 		if (NULL != (item_index = (zbx_lld_item_index_t *)zbx_hashset_search(items_index, &item_index_local)))
5083 		{
5084 			master = item_index->item;
5085 			zbx_vector_ptr_append(&master->dependent_items, item);
5086 		}
5087 	}
5088 
5089 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
5090 }
5091 
5092 /******************************************************************************
5093  *                                                                            *
5094  * Function: lld_update_items                                                 *
5095  *                                                                            *
5096  * Purpose: add or update discovered items                                    *
5097  *                                                                            *
5098  * Return value: SUCCEED - if items were successfully added/updated or        *
5099  *                         adding/updating was not necessary                  *
5100  *               FAIL    - items cannot be added/updated                      *
5101  *                                                                            *
5102  ******************************************************************************/
lld_update_items(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * lld_rows,char ** error,int lifetime,int lastcheck)5103 int	lld_update_items(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *lld_rows, char **error,
5104 		int lifetime, int lastcheck)
5105 {
5106 	const char		*__function_name = "lld_update_items";
5107 
5108 	zbx_vector_ptr_t	applications, application_prototypes, items, item_prototypes, item_dependencies;
5109 	zbx_hashset_t		applications_index, items_index, items_applications;
5110 	int			ret = SUCCEED, host_record_is_locked = 0;
5111 
5112 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
5113 
5114 	zbx_vector_ptr_create(&item_prototypes);
5115 
5116 	lld_item_prototypes_get(lld_ruleid, &item_prototypes);
5117 
5118 	if (0 == item_prototypes.values_num)
5119 		goto out;
5120 
5121 	zbx_vector_ptr_create(&application_prototypes);
5122 
5123 	lld_application_prototypes_get(lld_ruleid, &application_prototypes);
5124 
5125 	zbx_vector_ptr_create(&applications);
5126 	zbx_hashset_create(&applications_index, application_prototypes.values_num * lld_rows->values_num,
5127 			lld_application_index_hash_func, lld_application_index_compare_func);
5128 
5129 	zbx_vector_ptr_create(&items);
5130 	zbx_hashset_create(&items_index, item_prototypes.values_num * lld_rows->values_num, lld_item_index_hash_func,
5131 			lld_item_index_compare_func);
5132 
5133 	zbx_hashset_create(&items_applications, 100, lld_item_application_hash_func, lld_item_application_compare_func);
5134 
5135 	lld_applications_get(lld_ruleid, &applications);
5136 	lld_applications_make(&application_prototypes, lld_rows, &applications, &applications_index);
5137 	lld_applications_validate(hostid, lld_ruleid, &applications, &applications_index, error);
5138 
5139 	lld_item_application_prototypes_get(&item_prototypes, &application_prototypes);
5140 
5141 	lld_items_get(&item_prototypes, &items);
5142 	lld_items_make(&item_prototypes, lld_rows, &items, &items_index, error);
5143 	lld_items_preproc_make(&item_prototypes, &items, error);
5144 
5145 	lld_link_dependent_items(&items, &items_index);
5146 
5147 	zbx_vector_ptr_create(&item_dependencies);
5148 	lld_item_dependencies_get(&item_prototypes, &item_dependencies);
5149 
5150 	lld_items_validate(hostid, &items, &item_prototypes, &item_dependencies, error);
5151 
5152 	lld_items_applications_get(lld_ruleid, &items_applications);
5153 	lld_items_applications_make(&item_prototypes, &items, &applications_index, &items_applications);
5154 
5155 	DBbegin();
5156 
5157 	if (SUCCEED == lld_items_save(hostid, &item_prototypes, &items, &items_index, &host_record_is_locked) &&
5158 			SUCCEED == lld_items_preproc_save(hostid, &items, &host_record_is_locked) &&
5159 			SUCCEED == lld_applications_save(hostid, &applications, &application_prototypes,
5160 					&host_record_is_locked))
5161 	{
5162 		lld_items_applications_save(&items_applications, &items);
5163 
5164 		if (ZBX_DB_OK != DBcommit())
5165 		{
5166 			ret = FAIL;
5167 			goto clean;
5168 		}
5169 	}
5170 	else
5171 	{
5172 		ret = FAIL;
5173 		DBrollback();
5174 		goto clean;
5175 	}
5176 
5177 	lld_item_links_populate(&item_prototypes, lld_rows, &items_index);
5178 	lld_remove_lost_items(&items, lifetime, lastcheck);
5179 	lld_remove_lost_applications(lld_ruleid, &applications, lifetime, lastcheck);
5180 clean:
5181 	zbx_hashset_destroy(&items_applications);
5182 	zbx_hashset_destroy(&items_index);
5183 
5184 	zbx_vector_ptr_clear_ext(&item_dependencies, zbx_ptr_free);
5185 	zbx_vector_ptr_destroy(&item_dependencies);
5186 
5187 	zbx_vector_ptr_clear_ext(&items, (zbx_clean_func_t)lld_item_free);
5188 	zbx_vector_ptr_destroy(&items);
5189 
5190 	zbx_hashset_destroy(&applications_index);
5191 
5192 	zbx_vector_ptr_clear_ext(&applications, (zbx_clean_func_t)lld_application_free);
5193 	zbx_vector_ptr_destroy(&applications);
5194 
5195 	zbx_vector_ptr_clear_ext(&application_prototypes, (zbx_clean_func_t)lld_application_prototype_free);
5196 	zbx_vector_ptr_destroy(&application_prototypes);
5197 
5198 	zbx_vector_ptr_clear_ext(&item_prototypes, (zbx_clean_func_t)lld_item_prototype_free);
5199 out:
5200 	zbx_vector_ptr_destroy(&item_prototypes);
5201 
5202 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
5203 
5204 	return ret;
5205 }
5206