1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "lld.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxalgo.h"
24 #include "zbxserver.h"
25
26 typedef struct
27 {
28 zbx_uint64_t hostmacroid;
29 char *macro;
30 char *value;
31 char *description;
32 unsigned char type;
33 #define ZBX_FLAG_LLD_HOSTMACRO_UPDATE_VALUE __UINT64_C(0x00000001)
34 #define ZBX_FLAG_LLD_HOSTMACRO_UPDATE_DESCRIPTION __UINT64_C(0x00000002)
35 #define ZBX_FLAG_LLD_HOSTMACRO_UPDATE_TYPE __UINT64_C(0x00000004)
36 #define ZBX_FLAG_LLD_HOSTMACRO_UPDATE \
37 (ZBX_FLAG_LLD_HOSTMACRO_UPDATE_VALUE | ZBX_FLAG_LLD_HOSTMACRO_UPDATE_DESCRIPTION | \
38 ZBX_FLAG_LLD_HOSTMACRO_UPDATE_TYPE)
39 #define ZBX_FLAG_LLD_HOSTMACRO_REMOVE __UINT64_C(0x00000008)
40 zbx_uint64_t flags;
41 }
42 zbx_lld_hostmacro_t;
43
lld_hostmacro_free(zbx_lld_hostmacro_t * hostmacro)44 static void lld_hostmacro_free(zbx_lld_hostmacro_t *hostmacro)
45 {
46 zbx_free(hostmacro->macro);
47 zbx_free(hostmacro->value);
48 zbx_free(hostmacro->description);
49 zbx_free(hostmacro);
50 }
51
52 typedef struct
53 {
54 char *community;
55 char *securityname;
56 char *authpassphrase;
57 char *privpassphrase;
58 char *contextname;
59 unsigned char securitylevel;
60 unsigned char authprotocol;
61 unsigned char privprotocol;
62 unsigned char version;
63 unsigned char bulk;
64 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_TYPE __UINT64_C(0x00000001) /* interface_snmp.type */
65 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_BULK __UINT64_C(0x00000002) /* interface_snmp.bulk */
66 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_COMMUNITY __UINT64_C(0x00000004) /* interface_snmp.community */
67 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECNAME __UINT64_C(0x00000008) /* interface_snmp.securityname */
68 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECLEVEL __UINT64_C(0x00000010) /* interface_snmp.securitylevel */
69 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPASS __UINT64_C(0x00000020) /* interface_snmp.authpassphrase */
70 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPASS __UINT64_C(0x00000040) /* interface_snmp.privpassphrase */
71 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPROTOCOL __UINT64_C(0x00000080) /* interface_snmp.authprotocol */
72 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPROTOCOL __UINT64_C(0x00000100) /* interface_snmp.privprotocol */
73 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_CONTEXT __UINT64_C(0x00000200) /* interface_snmp.contextname */
74 #define ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE \
75 (ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_TYPE | ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_BULK | \
76 ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_COMMUNITY | ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECNAME | \
77 ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECLEVEL | ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPASS | \
78 ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPASS | ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPROTOCOL | \
79 ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPROTOCOL | ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_CONTEXT)
80 #define ZBX_FLAG_LLD_INTERFACE_SNMP_CREATE __UINT64_C(0x00000400) /* new snmp data record*/
81 zbx_uint64_t flags;
82
83 }
84 zbx_lld_interface_snmp_t;
85
86 typedef struct
87 {
88 zbx_uint64_t interfaceid;
89 zbx_uint64_t parent_interfaceid;
90 char *ip;
91 char *dns;
92 char *port;
93 unsigned char main;
94 unsigned char main_orig;
95 unsigned char type;
96 unsigned char type_orig;
97 unsigned char useip;
98 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE __UINT64_C(0x00000001) /* interface.type field should be updated */
99 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN __UINT64_C(0x00000002) /* interface.main field should be updated */
100 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP __UINT64_C(0x00000004) /* interface.useip field should be updated */
101 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_IP __UINT64_C(0x00000008) /* interface.ip field should be updated */
102 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS __UINT64_C(0x00000010) /* interface.dns field should be updated */
103 #define ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT __UINT64_C(0x00000020) /* interface.port field should be updated */
104 #define ZBX_FLAG_LLD_INTERFACE_UPDATE \
105 (ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE | ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN | \
106 ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP | ZBX_FLAG_LLD_INTERFACE_UPDATE_IP | \
107 ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS | ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT)
108 #define ZBX_FLAG_LLD_INTERFACE_REMOVE __UINT64_C(0x00000080) /* interfaces which should be deleted */
109 #define ZBX_FLAG_LLD_INTERFACE_SNMP_REMOVE __UINT64_C(0x00000100) /* snmp data which should be deleted */
110 #define ZBX_FLAG_LLD_INTERFACE_SNMP_DATA_EXISTS __UINT64_C(0x00000200) /* there is snmp data */
111 zbx_uint64_t flags;
112 union _data
113 {
114 zbx_lld_interface_snmp_t *snmp;
115 }
116 data;
117 }
118 zbx_lld_interface_t;
119
lld_interface_free(zbx_lld_interface_t * interface)120 static void lld_interface_free(zbx_lld_interface_t *interface)
121 {
122 zbx_free(interface->port);
123 zbx_free(interface->dns);
124 zbx_free(interface->ip);
125
126 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_DATA_EXISTS))
127 {
128 zbx_free(interface->data.snmp->community);
129 zbx_free(interface->data.snmp->securityname);
130 zbx_free(interface->data.snmp->authpassphrase);
131 zbx_free(interface->data.snmp->privpassphrase);
132 zbx_free(interface->data.snmp->contextname);
133 zbx_free(interface->data.snmp);
134 }
135
136 zbx_free(interface);
137 }
138
139 typedef struct
140 {
141 zbx_uint64_t hostid;
142 zbx_vector_uint64_t new_groupids; /* host groups which should be added */
143 zbx_vector_uint64_t lnk_templateids; /* templates which should be linked */
144 zbx_vector_uint64_t del_templateids; /* templates which should be unlinked */
145 zbx_vector_ptr_t new_hostmacros; /* host macros which should be added, deleted or updated */
146 zbx_vector_ptr_t interfaces;
147 zbx_vector_db_tag_ptr_t tags;
148 char *host_proto;
149 char *host;
150 char *host_orig;
151 char *name;
152 char *name_orig;
153 int lastcheck;
154 int ts_delete;
155 #define ZBX_FLAG_LLD_HOST_DISCOVERED __UINT64_C(0x00000001) /* hosts which should be updated or added */
156 #define ZBX_FLAG_LLD_HOST_UPDATE_HOST __UINT64_C(0x00000002) /* hosts.host and host_discovery.host fields should be updated */
157 #define ZBX_FLAG_LLD_HOST_UPDATE_NAME __UINT64_C(0x00000004) /* hosts.name field should be updated */
158 #define ZBX_FLAG_LLD_HOST_UPDATE_PROXY __UINT64_C(0x00000008) /* hosts.proxy_hostid field should be updated */
159 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH __UINT64_C(0x00000010) /* hosts.ipmi_authtype field should be updated */
160 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV __UINT64_C(0x00000020) /* hosts.ipmi_privilege field should be updated */
161 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER __UINT64_C(0x00000040) /* hosts.ipmi_username field should be updated */
162 #define ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS __UINT64_C(0x00000080) /* hosts.ipmi_password field should be updated */
163 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT __UINT64_C(0x00000100) /* hosts.tls_connect field should be updated */
164 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT __UINT64_C(0x00000200) /* hosts.tls_accept field should be updated */
165 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER __UINT64_C(0x00000400) /* hosts.tls_issuer field should be updated */
166 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT __UINT64_C(0x00000800) /* hosts.tls_subject field should be updated */
167 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY __UINT64_C(0x00001000) /* hosts.tls_psk_identity field should be updated */
168 #define ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK __UINT64_C(0x00002000) /* hosts.tls_psk field should be updated */
169 #define ZBX_FLAG_LLD_HOST_UPDATE_CUSTOM_INTERFACES __UINT64_C(0x00004000) /* hosts.custom_interfaces field should be updated */
170
171 #define ZBX_FLAG_LLD_HOST_UPDATE \
172 (ZBX_FLAG_LLD_HOST_UPDATE_HOST | ZBX_FLAG_LLD_HOST_UPDATE_NAME | \
173 ZBX_FLAG_LLD_HOST_UPDATE_PROXY | ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH | \
174 ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV | ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER | \
175 ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS | ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT | \
176 ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT | ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER | \
177 ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT | ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY | \
178 ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK | ZBX_FLAG_LLD_HOST_UPDATE_CUSTOM_INTERFACES)
179 zbx_uint64_t flags;
180 const struct zbx_json_parse *jp_row;
181 char inventory_mode;
182 char inventory_mode_orig;
183 unsigned char status;
184 unsigned char custom_interfaces;
185 }
186 zbx_lld_host_t;
187
lld_host_free(zbx_lld_host_t * host)188 static void lld_host_free(zbx_lld_host_t *host)
189 {
190 zbx_vector_uint64_destroy(&host->new_groupids);
191 zbx_vector_uint64_destroy(&host->lnk_templateids);
192 zbx_vector_uint64_destroy(&host->del_templateids);
193 zbx_vector_ptr_clear_ext(&host->new_hostmacros, (zbx_clean_func_t)lld_hostmacro_free);
194 zbx_vector_ptr_destroy(&host->new_hostmacros);
195 zbx_vector_db_tag_ptr_clear_ext(&host->tags, zbx_db_tag_free);
196 zbx_vector_db_tag_ptr_destroy(&host->tags);
197 zbx_vector_ptr_clear_ext(&host->interfaces, (zbx_clean_func_t)lld_interface_free);
198 zbx_vector_ptr_destroy(&host->interfaces);
199 zbx_free(host->host_proto);
200 zbx_free(host->host);
201 zbx_free(host->host_orig);
202 zbx_free(host->name);
203 zbx_free(host->name_orig);
204 zbx_free(host);
205 }
206
207 typedef struct
208 {
209 zbx_uint64_t group_prototypeid;
210 char *name;
211 }
212 zbx_lld_group_prototype_t;
213
lld_group_prototype_free(zbx_lld_group_prototype_t * group_prototype)214 static void lld_group_prototype_free(zbx_lld_group_prototype_t *group_prototype)
215 {
216 zbx_free(group_prototype->name);
217 zbx_free(group_prototype);
218 }
219
220 typedef struct
221 {
222 zbx_uint64_t groupid;
223 zbx_uint64_t group_prototypeid;
224 zbx_vector_ptr_t hosts;
225 char *name_proto;
226 char *name;
227 char *name_orig;
228 int lastcheck;
229 int ts_delete;
230 #define ZBX_FLAG_LLD_GROUP_DISCOVERED __UINT64_C(0x00000001) /* groups which should be updated or added */
231 #define ZBX_FLAG_LLD_GROUP_UPDATE_NAME __UINT64_C(0x00000002) /* groups.name field should be updated */
232 #define ZBX_FLAG_LLD_GROUP_UPDATE ZBX_FLAG_LLD_GROUP_UPDATE_NAME
233 zbx_uint64_t flags;
234 }
235 zbx_lld_group_t;
236
lld_group_free(zbx_lld_group_t * group)237 static void lld_group_free(zbx_lld_group_t *group)
238 {
239 /* zbx_vector_ptr_clear_ext(&group->hosts, (zbx_clean_func_t)lld_host_free); is not missing here */
240 zbx_vector_ptr_destroy(&group->hosts);
241 zbx_free(group->name_proto);
242 zbx_free(group->name);
243 zbx_free(group->name_orig);
244 zbx_free(group);
245 }
246
247 typedef struct
248 {
249 char *name;
250 /* permission pair (usrgrpid, permission) */
251 zbx_vector_uint64_pair_t rights;
252 /* reference to the inherited rights */
253 zbx_vector_uint64_pair_t *prights;
254 }
255 zbx_lld_group_rights_t;
256
257 static void lld_host_update_tags(zbx_lld_host_t *host, const zbx_vector_db_tag_ptr_t *tags,
258 const zbx_vector_ptr_t *lld_macros, char **info);
259
260 /******************************************************************************
261 * *
262 * Function: lld_hosts_get_tags *
263 * *
264 * Purpose: retrieves tags of the existing hosts *
265 * *
266 * Parameters: hosts - [IN/OUT] list of hosts *
267 * *
268 ******************************************************************************/
lld_hosts_get_tags(zbx_vector_ptr_t * hosts)269 static void lld_hosts_get_tags(zbx_vector_ptr_t *hosts)
270 {
271 zbx_vector_uint64_t hostids;
272 int i;
273 zbx_lld_host_t *host;
274 DB_RESULT result;
275 DB_ROW row;
276 char *sql = NULL;
277 size_t sql_alloc = 0, sql_offset = 0;
278 zbx_uint64_t hostid;
279 zbx_db_tag_t *tag;
280
281 zbx_vector_ptr_sort(hosts, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
282 zbx_vector_uint64_create(&hostids);
283
284 for (i = 0; i < hosts->values_num; i++)
285 {
286 host = (zbx_lld_host_t *)hosts->values[i];
287 zbx_vector_uint64_append(&hostids, host->hostid);
288 }
289
290 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select hosttagid,hostid,tag,value from host_tag where");
291 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
292 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by hostid");
293
294 result = DBselect("%s", sql);
295
296 i = 0;
297 host = (zbx_lld_host_t *)hosts->values[i];
298
299 while (NULL != (row = DBfetch(result)))
300 {
301 ZBX_STR2UINT64(hostid, row[1]);
302 while (hostid != host->hostid)
303 {
304 if (++i == hosts->values_num)
305 {
306 THIS_SHOULD_NEVER_HAPPEN;
307 goto out;
308 }
309 host = (zbx_lld_host_t *)hosts->values[i];
310 }
311
312 tag = (zbx_db_tag_t *)zbx_malloc(NULL, sizeof(zbx_db_tag_t));
313 ZBX_STR2UINT64(tag->tagid, row[0]);
314 tag->tag = zbx_strdup(NULL, row[2]);
315 tag->value = zbx_strdup(NULL, row[3]);
316 tag->flags = 0;
317 zbx_vector_db_tag_ptr_append(&host->tags, tag);
318 }
319 out:
320 for (i = 0; i < hosts->values_num; i++)
321 {
322 host = (zbx_lld_host_t *)hosts->values[i];
323 zbx_vector_db_tag_ptr_sort(&host->tags, zbx_db_tag_compare_func);
324 }
325
326 DBfree_result(result);
327 zbx_free(sql);
328 zbx_vector_uint64_destroy(&hostids);
329 }
330
331 /******************************************************************************
332 * *
333 * Function: lld_hosts_get *
334 * *
335 * Purpose: retrieves existing hosts for the specified host prototype *
336 * *
337 * Parameters: parent_hostid - [IN] host prototype identifier *
338 * hosts - [OUT] list of hosts *
339 * *
340 ******************************************************************************/
lld_hosts_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts,zbx_uint64_t proxy_hostid,char ipmi_authtype,unsigned char ipmi_privilege,const char * ipmi_username,const char * ipmi_password,unsigned char tls_connect,unsigned char tls_accept,const char * tls_issuer,const char * tls_subject,const char * tls_psk_identity,const char * tls_psk)341 static void lld_hosts_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts, zbx_uint64_t proxy_hostid,
342 char ipmi_authtype, unsigned char ipmi_privilege, const char *ipmi_username, const char *ipmi_password,
343 unsigned char tls_connect, unsigned char tls_accept, const char *tls_issuer,
344 const char *tls_subject, const char *tls_psk_identity, const char *tls_psk)
345 {
346 DB_RESULT result;
347 DB_ROW row;
348 zbx_lld_host_t *host;
349 zbx_uint64_t db_proxy_hostid;
350
351 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
352
353 result = DBselect(
354 "select hd.hostid,hd.host,hd.lastcheck,hd.ts_delete,h.host,h.name,h.proxy_hostid,"
355 "h.ipmi_authtype,h.ipmi_privilege,h.ipmi_username,h.ipmi_password,hi.inventory_mode,"
356 "h.tls_connect,h.tls_accept,h.tls_issuer,h.tls_subject,h.tls_psk_identity,h.tls_psk,"
357 "h.custom_interfaces"
358 " from host_discovery hd"
359 " join hosts h"
360 " on hd.hostid=h.hostid"
361 " left join host_inventory hi"
362 " on hd.hostid=hi.hostid"
363 " where hd.parent_hostid=" ZBX_FS_UI64,
364 parent_hostid);
365
366 while (NULL != (row = DBfetch(result)))
367 {
368 host = (zbx_lld_host_t *)zbx_malloc(NULL, sizeof(zbx_lld_host_t));
369
370 ZBX_STR2UINT64(host->hostid, row[0]);
371 host->host_proto = zbx_strdup(NULL, row[1]);
372 host->lastcheck = atoi(row[2]);
373 host->ts_delete = atoi(row[3]);
374 host->host = zbx_strdup(NULL, row[4]);
375 host->host_orig = NULL;
376 host->name = zbx_strdup(NULL, row[5]);
377 host->name_orig = NULL;
378 host->flags = 0x00;
379 ZBX_STR2UCHAR(host->custom_interfaces, row[18]);
380
381 ZBX_DBROW2UINT64(db_proxy_hostid, row[6]);
382 if (db_proxy_hostid != proxy_hostid)
383 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_PROXY;
384
385 if ((char)atoi(row[7]) != ipmi_authtype)
386 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH;
387
388 if ((unsigned char)atoi(row[8]) != ipmi_privilege)
389 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV;
390
391 if (0 != strcmp(row[9], ipmi_username))
392 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER;
393
394 if (0 != strcmp(row[10], ipmi_password))
395 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS;
396
397 if (atoi(row[12]) != tls_connect)
398 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT;
399
400 if (atoi(row[13]) != tls_accept)
401 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT;
402
403 if (0 != strcmp(tls_issuer, row[14]))
404 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER;
405
406 if (0 != strcmp(tls_subject, row[15]))
407 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT;
408
409 if (0 != strcmp(tls_psk_identity, row[16]))
410 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY;
411
412 if (0 != strcmp(tls_psk, row[17]))
413 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK;
414
415 if (SUCCEED == DBis_null(row[11]))
416 host->inventory_mode_orig = HOST_INVENTORY_DISABLED;
417 else
418 host->inventory_mode_orig = (char)atoi(row[11]);
419
420 zbx_vector_uint64_create(&host->new_groupids);
421 zbx_vector_uint64_create(&host->lnk_templateids);
422 zbx_vector_uint64_create(&host->del_templateids);
423 zbx_vector_ptr_create(&host->new_hostmacros);
424 zbx_vector_db_tag_ptr_create(&host->tags);
425 zbx_vector_ptr_create(&host->interfaces);
426
427 zbx_vector_ptr_append(hosts, host);
428 }
429 DBfree_result(result);
430
431 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
432 }
433
434 /******************************************************************************
435 * *
436 * Function: lld_hosts_validate *
437 * *
438 * Parameters: hosts - [IN] list of hosts; should be sorted by hostid *
439 * *
440 ******************************************************************************/
lld_hosts_validate(zbx_vector_ptr_t * hosts,char ** error)441 static void lld_hosts_validate(zbx_vector_ptr_t *hosts, char **error)
442 {
443 DB_RESULT result;
444 DB_ROW row;
445 int i, j;
446 zbx_lld_host_t *host, *host_b;
447 zbx_vector_uint64_t hostids;
448 zbx_vector_str_t tnames, vnames;
449
450 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
451
452 zbx_vector_uint64_create(&hostids);
453 zbx_vector_str_create(&tnames); /* list of technical host names */
454 zbx_vector_str_create(&vnames); /* list of visible host names */
455
456 /* checking a host name validity */
457 for (i = 0; i < hosts->values_num; i++)
458 {
459 char *ch_error;
460
461 host = (zbx_lld_host_t *)hosts->values[i];
462
463 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
464 continue;
465
466 /* only new hosts or hosts with changed host name will be validated */
467 if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
468 continue;
469
470 /* host name is valid? */
471 if (SUCCEED == zbx_check_hostname(host->host, &ch_error))
472 continue;
473
474 *error = zbx_strdcatf(*error, "Cannot %s host \"%s\": %s.\n",
475 (0 != host->hostid ? "update" : "create"), host->host, ch_error);
476
477 zbx_free(ch_error);
478
479 if (0 != host->hostid)
480 {
481 lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
482 ZBX_FLAG_LLD_HOST_UPDATE_HOST);
483 }
484 else
485 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
486 }
487
488 /* checking a visible host name validity */
489 for (i = 0; i < hosts->values_num; i++)
490 {
491 host = (zbx_lld_host_t *)hosts->values[i];
492
493 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
494 continue;
495
496 /* only new hosts or hosts with changed visible name will be validated */
497 if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
498 continue;
499
500 /* visible host name is valid utf8 sequence and has a valid length */
501 if (SUCCEED == zbx_is_utf8(host->name) && '\0' != *host->name &&
502 HOST_NAME_LEN >= zbx_strlen_utf8(host->name))
503 {
504 continue;
505 }
506
507 zbx_replace_invalid_utf8(host->name);
508 *error = zbx_strdcatf(*error, "Cannot %s host: invalid visible host name \"%s\".\n",
509 (0 != host->hostid ? "update" : "create"), host->name);
510
511 if (0 != host->hostid)
512 {
513 lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
514 ZBX_FLAG_LLD_HOST_UPDATE_NAME);
515 }
516 else
517 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
518 }
519
520 /* checking duplicated host names */
521 for (i = 0; i < hosts->values_num; i++)
522 {
523 host = (zbx_lld_host_t *)hosts->values[i];
524
525 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
526 continue;
527
528 /* only new hosts or hosts with changed host name will be validated */
529 if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
530 continue;
531
532 for (j = 0; j < hosts->values_num; j++)
533 {
534 host_b = (zbx_lld_host_t *)hosts->values[j];
535
536 if (0 == (host_b->flags & ZBX_FLAG_LLD_HOST_DISCOVERED) || i == j)
537 continue;
538
539 if (0 != strcmp(host->host, host_b->host))
540 continue;
541
542 *error = zbx_strdcatf(*error, "Cannot %s host:"
543 " host with the same name \"%s\" already exists.\n",
544 (0 != host->hostid ? "update" : "create"), host->host);
545
546 if (0 != host->hostid)
547 {
548 lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
549 ZBX_FLAG_LLD_HOST_UPDATE_HOST);
550 }
551 else
552 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
553 }
554 }
555
556 /* checking duplicated visible host names */
557 for (i = 0; i < hosts->values_num; i++)
558 {
559 host = (zbx_lld_host_t *)hosts->values[i];
560
561 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
562 continue;
563
564 /* only new hosts or hosts with changed visible name will be validated */
565 if (0 != host->hostid && 0 == (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
566 continue;
567
568 for (j = 0; j < hosts->values_num; j++)
569 {
570 host_b = (zbx_lld_host_t *)hosts->values[j];
571
572 if (0 == (host_b->flags & ZBX_FLAG_LLD_HOST_DISCOVERED) || i == j)
573 continue;
574
575 if (0 != strcmp(host->name, host_b->name))
576 continue;
577
578 *error = zbx_strdcatf(*error, "Cannot %s host:"
579 " host with the same visible name \"%s\" already exists.\n",
580 (0 != host->hostid ? "update" : "create"), host->name);
581
582 if (0 != host->hostid)
583 {
584 lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
585 ZBX_FLAG_LLD_HOST_UPDATE_NAME);
586 }
587 else
588 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
589 }
590 }
591
592 /* checking duplicated host names and visible host names in DB */
593
594 for (i = 0; i < hosts->values_num; i++)
595 {
596 host = (zbx_lld_host_t *)hosts->values[i];
597
598 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
599 continue;
600
601 if (0 != host->hostid)
602 zbx_vector_uint64_append(&hostids, host->hostid);
603
604 if (0 == host->hostid || 0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
605 zbx_vector_str_append(&tnames, host->host);
606
607 if (0 == host->hostid || 0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
608 zbx_vector_str_append(&vnames, host->name);
609 }
610
611 if (0 != tnames.values_num || 0 != vnames.values_num)
612 {
613 char *sql = NULL;
614 size_t sql_alloc = 0, sql_offset = 0;
615
616 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
617 "select host,name"
618 " from hosts"
619 " where status in (%d,%d,%d)"
620 " and flags<>%d"
621 " and",
622 HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, HOST_STATUS_TEMPLATE,
623 ZBX_FLAG_DISCOVERY_PROTOTYPE);
624
625 if (0 != tnames.values_num && 0 != vnames.values_num)
626 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " (");
627
628 if (0 != tnames.values_num)
629 {
630 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "host",
631 (const char **)tnames.values, tnames.values_num);
632 }
633
634 if (0 != tnames.values_num && 0 != vnames.values_num)
635 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " or");
636
637 if (0 != vnames.values_num)
638 {
639 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
640 (const char **)vnames.values, vnames.values_num);
641 }
642
643 if (0 != tnames.values_num && 0 != vnames.values_num)
644 zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ')');
645
646 if (0 != hostids.values_num)
647 {
648 zbx_vector_uint64_sort(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
649 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
650 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
651 hostids.values, hostids.values_num);
652 }
653
654 result = DBselect("%s", sql);
655
656 while (NULL != (row = DBfetch(result)))
657 {
658 for (i = 0; i < hosts->values_num; i++)
659 {
660 host = (zbx_lld_host_t *)hosts->values[i];
661
662 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
663 continue;
664
665 if (0 == strcmp(host->host, row[0]))
666 {
667 *error = zbx_strdcatf(*error, "Cannot %s host:"
668 " host with the same name \"%s\" already exists.\n",
669 (0 != host->hostid ? "update" : "create"), host->host);
670
671 if (0 != host->hostid)
672 {
673 lld_field_str_rollback(&host->host, &host->host_orig, &host->flags,
674 ZBX_FLAG_LLD_HOST_UPDATE_HOST);
675 }
676 else
677 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
678 }
679
680 if (0 == strcmp(host->name, row[1]))
681 {
682 *error = zbx_strdcatf(*error, "Cannot %s host:"
683 " host with the same visible name \"%s\" already exists.\n",
684 (0 != host->hostid ? "update" : "create"), host->name);
685
686 if (0 != host->hostid)
687 {
688 lld_field_str_rollback(&host->name, &host->name_orig, &host->flags,
689 ZBX_FLAG_LLD_HOST_UPDATE_NAME);
690 }
691 else
692 host->flags &= ~ZBX_FLAG_LLD_HOST_DISCOVERED;
693 }
694 }
695 }
696 DBfree_result(result);
697
698 zbx_free(sql);
699 }
700
701 zbx_vector_str_destroy(&vnames);
702 zbx_vector_str_destroy(&tnames);
703 zbx_vector_uint64_destroy(&hostids);
704
705 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
706 }
707
lld_host_make(zbx_vector_ptr_t * hosts,const char * host_proto,const char * name_proto,char inventory_mode_proto,unsigned char status_proto,unsigned char discover_proto,zbx_vector_db_tag_ptr_t * tags,const zbx_lld_row_t * lld_row,const zbx_vector_ptr_t * lld_macros,char ** info,unsigned char custom_iface)708 static zbx_lld_host_t *lld_host_make(zbx_vector_ptr_t *hosts, const char *host_proto, const char *name_proto,
709 char inventory_mode_proto, unsigned char status_proto, unsigned char discover_proto,
710 zbx_vector_db_tag_ptr_t *tags, const zbx_lld_row_t *lld_row, const zbx_vector_ptr_t *lld_macros,
711 char **info, unsigned char custom_iface)
712 {
713 char *buffer = NULL;
714 int i, host_found = 0;
715 zbx_lld_host_t *host;
716 zbx_vector_db_tag_ptr_t tmp_tags;
717
718 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
719
720 for (i = 0; i < hosts->values_num; i++)
721 {
722 host = (zbx_lld_host_t *)hosts->values[i];
723
724 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
725 continue;
726
727 buffer = zbx_strdup(buffer, host->host_proto);
728 substitute_lld_macros(&buffer, &lld_row->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
729 zbx_lrtrim(buffer, ZBX_WHITESPACE);
730
731 if (0 == strcmp(host->host, buffer))
732 {
733 host_found = 1;
734 break;
735 }
736 }
737
738 zbx_vector_db_tag_ptr_create(&tmp_tags);
739
740 if (0 == host_found)
741 {
742 host = (zbx_lld_host_t *)zbx_malloc(NULL, sizeof(zbx_lld_host_t));
743
744 host->hostid = 0;
745 host->host_proto = NULL;
746 host->lastcheck = 0;
747 host->ts_delete = 0;
748 host->host = zbx_strdup(NULL, host_proto);
749 host->host_orig = NULL;
750 substitute_lld_macros(&host->host, &lld_row->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
751 zbx_lrtrim(host->host, ZBX_WHITESPACE);
752
753 host->status = status_proto;
754 host->inventory_mode = inventory_mode_proto;
755 host->custom_interfaces = custom_iface;
756
757 zbx_vector_uint64_create(&host->lnk_templateids);
758
759 lld_override_host(&lld_row->overrides, host->host, &host->lnk_templateids, &host->inventory_mode,
760 &tmp_tags, &host->status, &discover_proto);
761
762 if (ZBX_PROTOTYPE_NO_DISCOVER == discover_proto)
763 {
764 zbx_vector_uint64_destroy(&host->lnk_templateids);
765 zbx_free(host->host);
766 zbx_free(host);
767 goto out;
768 }
769 else
770 {
771 host->name = zbx_strdup(NULL, name_proto);
772 substitute_lld_macros(&host->name, &lld_row->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
773 zbx_lrtrim(host->name, ZBX_WHITESPACE);
774 host->name_orig = NULL;
775 zbx_vector_uint64_create(&host->new_groupids);
776 zbx_vector_uint64_create(&host->del_templateids);
777 zbx_vector_ptr_create(&host->new_hostmacros);
778 zbx_vector_db_tag_ptr_create(&host->tags);
779 zbx_vector_ptr_create(&host->interfaces);
780 host->flags = ZBX_FLAG_LLD_HOST_DISCOVERED;
781
782 zbx_vector_ptr_append(hosts, host);
783 }
784 }
785 else
786 {
787 /* host technical name */
788 if (0 != strcmp(host->host_proto, host_proto)) /* the new host prototype differs */
789 {
790 host->host_orig = host->host;
791 host->host = zbx_strdup(NULL, host_proto);
792 substitute_lld_macros(&host->host, &lld_row->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
793 zbx_lrtrim(host->host, ZBX_WHITESPACE);
794 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_HOST;
795 }
796
797 host->inventory_mode = inventory_mode_proto;
798
799 if (host->custom_interfaces != custom_iface)
800 {
801 host->custom_interfaces = custom_iface;
802 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_CUSTOM_INTERFACES;
803 }
804
805 lld_override_host(&lld_row->overrides, host->host, &host->lnk_templateids, &host->inventory_mode, &tmp_tags,
806 NULL, &discover_proto);
807
808 /* host visible name */
809 buffer = zbx_strdup(buffer, name_proto);
810 substitute_lld_macros(&buffer, &lld_row->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
811 zbx_lrtrim(buffer, ZBX_WHITESPACE);
812 if (0 != strcmp(host->name, buffer))
813 {
814 host->name_orig = host->name;
815 host->name = buffer;
816 buffer = NULL;
817 host->flags |= ZBX_FLAG_LLD_HOST_UPDATE_NAME;
818 }
819
820 if (ZBX_PROTOTYPE_NO_DISCOVER != discover_proto)
821 host->flags |= ZBX_FLAG_LLD_HOST_DISCOVERED;
822 }
823
824 host->jp_row = &lld_row->jp_row;
825
826 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
827 {
828 zbx_vector_db_tag_ptr_append_array(&tmp_tags, tags->values, tags->values_num);
829 lld_host_update_tags(host, &tmp_tags, lld_macros, info);
830 }
831 out:
832 zbx_vector_db_tag_ptr_destroy(&tmp_tags);
833
834 zbx_free(buffer);
835
836 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __func__, (void *)host);
837
838 return host;
839 }
840
841 /******************************************************************************
842 * *
843 * Function: lld_simple_groups_get *
844 * *
845 * Purpose: retrieve list of host groups which should be present on the each *
846 * discovered host *
847 * *
848 * Parameters: parent_hostid - [IN] host prototype identifier *
849 * groupids - [OUT] sorted list of host groups *
850 * *
851 ******************************************************************************/
lld_simple_groups_get(zbx_uint64_t parent_hostid,zbx_vector_uint64_t * groupids)852 static void lld_simple_groups_get(zbx_uint64_t parent_hostid, zbx_vector_uint64_t *groupids)
853 {
854 DB_RESULT result;
855 DB_ROW row;
856 zbx_uint64_t groupid;
857
858 result = DBselect(
859 "select groupid"
860 " from group_prototype"
861 " where groupid is not null"
862 " and hostid=" ZBX_FS_UI64,
863 parent_hostid);
864
865 while (NULL != (row = DBfetch(result)))
866 {
867 ZBX_STR2UINT64(groupid, row[0]);
868 zbx_vector_uint64_append(groupids, groupid);
869 }
870 DBfree_result(result);
871
872 zbx_vector_uint64_sort(groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
873 }
874
875 /******************************************************************************
876 * *
877 * Function: lld_hostgroups_make *
878 * *
879 * Parameters: groupids - [IN] sorted list of host group ids which *
880 * should be present on the each *
881 * discovered host (Groups) *
882 * hosts - [IN/OUT] list of hosts *
883 * should be sorted by hostid *
884 * groups - [IN] list of host groups (Group prototypes)*
885 * del_hostgroupids - [OUT] sorted list of host groups which *
886 * should be deleted *
887 * *
888 ******************************************************************************/
lld_hostgroups_make(const zbx_vector_uint64_t * groupids,zbx_vector_ptr_t * hosts,const zbx_vector_ptr_t * groups,zbx_vector_uint64_t * del_hostgroupids)889 static void lld_hostgroups_make(const zbx_vector_uint64_t *groupids, zbx_vector_ptr_t *hosts,
890 const zbx_vector_ptr_t *groups, zbx_vector_uint64_t *del_hostgroupids)
891 {
892 DB_RESULT result;
893 DB_ROW row;
894 int i, j;
895 zbx_vector_uint64_t hostids;
896 zbx_uint64_t hostgroupid, hostid, groupid;
897 zbx_lld_host_t *host;
898 const zbx_lld_group_t *group;
899
900 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
901
902 zbx_vector_uint64_create(&hostids);
903
904 for (i = 0; i < hosts->values_num; i++)
905 {
906 host = (zbx_lld_host_t *)hosts->values[i];
907
908 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
909 continue;
910
911 zbx_vector_uint64_reserve(&host->new_groupids, groupids->values_num);
912 for (j = 0; j < groupids->values_num; j++)
913 zbx_vector_uint64_append(&host->new_groupids, groupids->values[j]);
914
915 if (0 != host->hostid)
916 zbx_vector_uint64_append(&hostids, host->hostid);
917 }
918
919 for (i = 0; i < groups->values_num; i++)
920 {
921 group = (zbx_lld_group_t *)groups->values[i];
922
923 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED) || 0 == group->groupid)
924 continue;
925
926 for (j = 0; j < group->hosts.values_num; j++)
927 {
928 host = (zbx_lld_host_t *)group->hosts.values[j];
929
930 zbx_vector_uint64_append(&host->new_groupids, group->groupid);
931 }
932 }
933
934 for (i = 0; i < hosts->values_num; i++)
935 {
936 host = (zbx_lld_host_t *)hosts->values[i];
937 zbx_vector_uint64_sort(&host->new_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
938 }
939
940 if (0 != hostids.values_num)
941 {
942 char *sql = NULL;
943 size_t sql_alloc = 0, sql_offset = 0;
944
945 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
946 "select hostid,groupid,hostgroupid"
947 " from hosts_groups"
948 " where");
949 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
950
951 result = DBselect("%s", sql);
952
953 zbx_free(sql);
954
955 while (NULL != (row = DBfetch(result)))
956 {
957 ZBX_STR2UINT64(hostid, row[0]);
958 ZBX_STR2UINT64(groupid, row[1]);
959
960 if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
961 {
962 THIS_SHOULD_NEVER_HAPPEN;
963 continue;
964 }
965
966 host = (zbx_lld_host_t *)hosts->values[i];
967
968 if (FAIL == (i = zbx_vector_uint64_bsearch(&host->new_groupids, groupid,
969 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
970 {
971 /* host groups which should be unlinked */
972 ZBX_STR2UINT64(hostgroupid, row[2]);
973 zbx_vector_uint64_append(del_hostgroupids, hostgroupid);
974 }
975 else
976 {
977 /* host groups which are already added */
978 zbx_vector_uint64_remove(&host->new_groupids, i);
979 }
980 }
981 DBfree_result(result);
982
983 zbx_vector_uint64_sort(del_hostgroupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
984 }
985
986 zbx_vector_uint64_destroy(&hostids);
987
988 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
989 }
990
991 /******************************************************************************
992 * *
993 * Function: lld_group_prototypes_get *
994 * *
995 * Purpose: retrieve list of group prototypes *
996 * *
997 * Parameters: parent_hostid - [IN] host prototype identifier *
998 * group_prototypes - [OUT] sorted list of group prototypes *
999 * *
1000 ******************************************************************************/
lld_group_prototypes_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * group_prototypes)1001 static void lld_group_prototypes_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *group_prototypes)
1002 {
1003 DB_RESULT result;
1004 DB_ROW row;
1005 zbx_lld_group_prototype_t *group_prototype;
1006
1007 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1008
1009 result = DBselect(
1010 "select group_prototypeid,name"
1011 " from group_prototype"
1012 " where groupid is null"
1013 " and hostid=" ZBX_FS_UI64,
1014 parent_hostid);
1015
1016 while (NULL != (row = DBfetch(result)))
1017 {
1018 group_prototype = (zbx_lld_group_prototype_t *)zbx_malloc(NULL, sizeof(zbx_lld_group_prototype_t));
1019
1020 ZBX_STR2UINT64(group_prototype->group_prototypeid, row[0]);
1021 group_prototype->name = zbx_strdup(NULL, row[1]);
1022
1023 zbx_vector_ptr_append(group_prototypes, group_prototype);
1024 }
1025 DBfree_result(result);
1026
1027 zbx_vector_ptr_sort(group_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1028
1029 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1030 }
1031
1032 /******************************************************************************
1033 * *
1034 * Function: lld_groups_get *
1035 * *
1036 * Purpose: retrieves existing groups for the specified host prototype *
1037 * *
1038 * Parameters: parent_hostid - [IN] host prototype identifier *
1039 * groups - [OUT] list of groups *
1040 * *
1041 ******************************************************************************/
lld_groups_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * groups)1042 static void lld_groups_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *groups)
1043 {
1044 DB_RESULT result;
1045 DB_ROW row;
1046 zbx_lld_group_t *group;
1047
1048 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1049
1050 result = DBselect(
1051 "select gd.groupid,gp.group_prototypeid,gd.name,gd.lastcheck,gd.ts_delete,g.name"
1052 " from group_prototype gp,group_discovery gd"
1053 " join hstgrp g"
1054 " on gd.groupid=g.groupid"
1055 " where gp.group_prototypeid=gd.parent_group_prototypeid"
1056 " and gp.hostid=" ZBX_FS_UI64,
1057 parent_hostid);
1058
1059 while (NULL != (row = DBfetch(result)))
1060 {
1061 group = (zbx_lld_group_t *)zbx_malloc(NULL, sizeof(zbx_lld_group_t));
1062
1063 ZBX_STR2UINT64(group->groupid, row[0]);
1064 ZBX_STR2UINT64(group->group_prototypeid, row[1]);
1065 zbx_vector_ptr_create(&group->hosts);
1066 group->name_proto = zbx_strdup(NULL, row[2]);
1067 group->lastcheck = atoi(row[3]);
1068 group->ts_delete = atoi(row[4]);
1069 group->name = zbx_strdup(NULL, row[5]);
1070 group->name_orig = NULL;
1071 group->flags = 0x00;
1072
1073 zbx_vector_ptr_append(groups, group);
1074 }
1075 DBfree_result(result);
1076
1077 zbx_vector_ptr_sort(groups, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1078
1079 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1080 }
1081
1082 /******************************************************************************
1083 * *
1084 * Function: lld_group_make *
1085 * *
1086 ******************************************************************************/
lld_group_make(zbx_vector_ptr_t * groups,zbx_uint64_t group_prototypeid,const char * name_proto,const struct zbx_json_parse * jp_row,const zbx_vector_ptr_t * lld_macros)1087 static zbx_lld_group_t *lld_group_make(zbx_vector_ptr_t *groups, zbx_uint64_t group_prototypeid,
1088 const char *name_proto, const struct zbx_json_parse *jp_row, const zbx_vector_ptr_t *lld_macros)
1089 {
1090 char *buffer = NULL;
1091 int i, group_found = 0;
1092 zbx_lld_group_t *group = NULL;
1093
1094 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1095
1096 for (i = 0; i < groups->values_num; i++)
1097 {
1098 group = (zbx_lld_group_t *)groups->values[i];
1099
1100 if (group->group_prototypeid != group_prototypeid)
1101 continue;
1102
1103 if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1104 continue;
1105
1106 buffer = zbx_strdup(buffer, group->name_proto);
1107 substitute_lld_macros(&buffer, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1108 zbx_lrtrim(buffer, ZBX_WHITESPACE);
1109
1110 if (0 == strcmp(group->name, buffer))
1111 {
1112 group_found = 1;
1113 break;
1114 }
1115 }
1116
1117 if (0 == group_found)
1118 {
1119 /* trying to find an already existing group */
1120
1121 buffer = zbx_strdup(buffer, name_proto);
1122 substitute_lld_macros(&buffer, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1123 zbx_lrtrim(buffer, ZBX_WHITESPACE);
1124
1125 for (i = 0; i < groups->values_num; i++)
1126 {
1127 group = (zbx_lld_group_t *)groups->values[i];
1128
1129 if (group->group_prototypeid != group_prototypeid)
1130 continue;
1131
1132 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1133 continue;
1134
1135 if (0 == strcmp(group->name, buffer))
1136 goto out;
1137 }
1138
1139 /* otherwise create a new group */
1140
1141 group = (zbx_lld_group_t *)zbx_malloc(NULL, sizeof(zbx_lld_group_t));
1142
1143 group->groupid = 0;
1144 group->group_prototypeid = group_prototypeid;
1145 zbx_vector_ptr_create(&group->hosts);
1146 group->name_proto = NULL;
1147 group->name = zbx_strdup(NULL, name_proto);
1148 substitute_lld_macros(&group->name, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1149 zbx_lrtrim(group->name, ZBX_WHITESPACE);
1150 group->name_orig = NULL;
1151 group->lastcheck = 0;
1152 group->ts_delete = 0;
1153 group->flags = 0x00;
1154 group->flags = ZBX_FLAG_LLD_GROUP_DISCOVERED;
1155
1156 zbx_vector_ptr_append(groups, group);
1157 }
1158 else
1159 {
1160 /* update an already existing group */
1161
1162 /* group name */
1163 buffer = zbx_strdup(buffer, name_proto);
1164 substitute_lld_macros(&buffer, jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1165 zbx_lrtrim(buffer, ZBX_WHITESPACE);
1166 if (0 != strcmp(group->name, buffer))
1167 {
1168 group->name_orig = group->name;
1169 group->name = buffer;
1170 buffer = NULL;
1171 group->flags |= ZBX_FLAG_LLD_GROUP_UPDATE_NAME;
1172 }
1173
1174 group->flags |= ZBX_FLAG_LLD_GROUP_DISCOVERED;
1175 }
1176 out:
1177 zbx_free(buffer);
1178
1179 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __func__, (void *)group);
1180
1181 return group;
1182 }
1183
1184 /******************************************************************************
1185 * *
1186 * Function: lld_groups_make *
1187 * *
1188 ******************************************************************************/
lld_groups_make(zbx_lld_host_t * host,zbx_vector_ptr_t * groups,const zbx_vector_ptr_t * group_prototypes,const struct zbx_json_parse * jp_row,const zbx_vector_ptr_t * lld_macros)1189 static void lld_groups_make(zbx_lld_host_t *host, zbx_vector_ptr_t *groups, const zbx_vector_ptr_t *group_prototypes,
1190 const struct zbx_json_parse *jp_row, const zbx_vector_ptr_t *lld_macros)
1191 {
1192 int i;
1193
1194 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1195
1196 for (i = 0; i < group_prototypes->values_num; i++)
1197 {
1198 const zbx_lld_group_prototype_t *group_prototype;
1199 zbx_lld_group_t *group;
1200
1201 group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[i];
1202
1203 group = lld_group_make(groups, group_prototype->group_prototypeid, group_prototype->name, jp_row,
1204 lld_macros);
1205
1206 zbx_vector_ptr_append(&group->hosts, host);
1207 }
1208
1209 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1210 }
1211
1212 /******************************************************************************
1213 * *
1214 * Function: lld_validate_group_name *
1215 * *
1216 * Purpose: validate group name *
1217 * *
1218 * Return value: SUCCEED - the group name is valid *
1219 * FAIL - otherwise *
1220 * *
1221 ******************************************************************************/
lld_validate_group_name(const char * name)1222 static int lld_validate_group_name(const char *name)
1223 {
1224 /* group name cannot be empty */
1225 if ('\0' == *name)
1226 return FAIL;
1227
1228 /* group name must contain valid utf8 characters */
1229 if (SUCCEED != zbx_is_utf8(name))
1230 return FAIL;
1231
1232 /* group name cannot exceed field limits */
1233 if (GROUP_NAME_LEN < zbx_strlen_utf8(name))
1234 return FAIL;
1235
1236 /* group name cannot contain trailing and leading slashes (/) */
1237 if ('/' == *name || '/' == name[strlen(name) - 1])
1238 return FAIL;
1239
1240 /* group name cannot contain several slashes (/) in a row */
1241 if (NULL != strstr(name, "//"))
1242 return FAIL;
1243
1244 return SUCCEED;
1245 }
1246
1247 /******************************************************************************
1248 * *
1249 * Function: lld_groups_validate *
1250 * *
1251 * Parameters: groups - [IN] list of groups; should be sorted by groupid *
1252 * *
1253 ******************************************************************************/
lld_groups_validate(zbx_vector_ptr_t * groups,char ** error)1254 static void lld_groups_validate(zbx_vector_ptr_t *groups, char **error)
1255 {
1256 DB_RESULT result;
1257 DB_ROW row;
1258 int i, j;
1259 zbx_lld_group_t *group, *group_b;
1260 zbx_vector_uint64_t groupids;
1261 zbx_vector_str_t names;
1262
1263 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1264
1265 zbx_vector_uint64_create(&groupids);
1266 zbx_vector_str_create(&names); /* list of group names */
1267
1268 /* checking a group name validity */
1269 for (i = 0; i < groups->values_num; i++)
1270 {
1271 group = (zbx_lld_group_t *)groups->values[i];
1272
1273 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1274 continue;
1275
1276 /* only new groups or groups with changed group name will be validated */
1277 if (0 != group->groupid && 0 == (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1278 continue;
1279
1280 if (SUCCEED == lld_validate_group_name(group->name))
1281 continue;
1282
1283 zbx_replace_invalid_utf8(group->name);
1284 *error = zbx_strdcatf(*error, "Cannot %s group: invalid group name \"%s\".\n",
1285 (0 != group->groupid ? "update" : "create"), group->name);
1286
1287 if (0 != group->groupid)
1288 {
1289 lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1290 ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1291 }
1292 else
1293 group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1294 }
1295
1296 /* checking duplicated group names */
1297 for (i = 0; i < groups->values_num; i++)
1298 {
1299 group = (zbx_lld_group_t *)groups->values[i];
1300
1301 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1302 continue;
1303
1304 /* only new groups or groups with changed group name will be validated */
1305 if (0 != group->groupid && 0 == (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1306 continue;
1307
1308 for (j = 0; j < groups->values_num; j++)
1309 {
1310 group_b = (zbx_lld_group_t *)groups->values[j];
1311
1312 if (0 == (group_b->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED) || i == j)
1313 continue;
1314
1315 if (0 != strcmp(group->name, group_b->name))
1316 continue;
1317
1318 *error = zbx_strdcatf(*error, "Cannot %s group:"
1319 " group with the same name \"%s\" already exists.\n",
1320 (0 != group->groupid ? "update" : "create"), group->name);
1321
1322 if (0 != group->groupid)
1323 {
1324 lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1325 ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1326 }
1327 else
1328 group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1329 }
1330 }
1331
1332 /* checking duplicated group names and group names in DB */
1333
1334 for (i = 0; i < groups->values_num; i++)
1335 {
1336 group = (zbx_lld_group_t *)groups->values[i];
1337
1338 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1339 continue;
1340
1341 if (0 != group->groupid)
1342 zbx_vector_uint64_append(&groupids, group->groupid);
1343
1344 if (0 == group->groupid || 0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1345 zbx_vector_str_append(&names, group->name);
1346 }
1347
1348 if (0 != names.values_num)
1349 {
1350 char *sql = NULL;
1351 size_t sql_alloc = 0, sql_offset = 0;
1352
1353 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select name from hstgrp where");
1354 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
1355 (const char **)names.values, names.values_num);
1356
1357 if (0 != groupids.values_num)
1358 {
1359 zbx_vector_uint64_sort(&groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1360 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
1361 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
1362 groupids.values, groupids.values_num);
1363 }
1364
1365 result = DBselect("%s", sql);
1366
1367 while (NULL != (row = DBfetch(result)))
1368 {
1369 for (i = 0; i < groups->values_num; i++)
1370 {
1371 group = (zbx_lld_group_t *)groups->values[i];
1372
1373 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1374 continue;
1375
1376 if (0 == strcmp(group->name, row[0]))
1377 {
1378 *error = zbx_strdcatf(*error, "Cannot %s group:"
1379 " group with the same name \"%s\" already exists.\n",
1380 (0 != group->groupid ? "update" : "create"), group->name);
1381
1382 if (0 != group->groupid)
1383 {
1384 lld_field_str_rollback(&group->name, &group->name_orig, &group->flags,
1385 ZBX_FLAG_LLD_GROUP_UPDATE_NAME);
1386 }
1387 else
1388 group->flags &= ~ZBX_FLAG_LLD_GROUP_DISCOVERED;
1389 }
1390 }
1391 }
1392 DBfree_result(result);
1393
1394 zbx_free(sql);
1395 }
1396
1397 zbx_vector_str_destroy(&names);
1398 zbx_vector_uint64_destroy(&groupids);
1399
1400 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1401 }
1402
1403 /******************************************************************************
1404 * *
1405 * Function: lld_group_rights_compare *
1406 * *
1407 * Purpose: sorting function to sort group rights vector by name *
1408 * *
1409 ******************************************************************************/
lld_group_rights_compare(const void * d1,const void * d2)1410 static int lld_group_rights_compare(const void *d1, const void *d2)
1411 {
1412 const zbx_lld_group_rights_t *r1 = *(const zbx_lld_group_rights_t **)d1;
1413 const zbx_lld_group_rights_t *r2 = *(const zbx_lld_group_rights_t **)d2;
1414
1415 return strcmp(r1->name, r2->name);
1416 }
1417
1418 /******************************************************************************
1419 * *
1420 * Function: lld_group_rights_append *
1421 * *
1422 * Purpose: append a new item to group rights vector *
1423 * *
1424 * Return value: Index of the added item. *
1425 * *
1426 ******************************************************************************/
lld_group_rights_append(zbx_vector_ptr_t * group_rights,const char * name)1427 static int lld_group_rights_append(zbx_vector_ptr_t *group_rights, const char *name)
1428 {
1429 zbx_lld_group_rights_t *rights;
1430
1431 rights = (zbx_lld_group_rights_t *)zbx_malloc(NULL, sizeof(zbx_lld_group_rights_t));
1432 rights->name = zbx_strdup(NULL, name);
1433 zbx_vector_uint64_pair_create(&rights->rights);
1434 rights->prights = NULL;
1435
1436 zbx_vector_ptr_append(group_rights, rights);
1437
1438 return group_rights->values_num - 1;
1439 }
1440
1441 /******************************************************************************
1442 * *
1443 * Function: lld_group_rights_free *
1444 * *
1445 * PUrpose: frees group rights data *
1446 * *
1447 ******************************************************************************/
lld_group_rights_free(zbx_lld_group_rights_t * rights)1448 static void lld_group_rights_free(zbx_lld_group_rights_t *rights)
1449 {
1450 zbx_free(rights->name);
1451 zbx_vector_uint64_pair_destroy(&rights->rights);
1452 zbx_free(rights);
1453 }
1454
1455 /******************************************************************************
1456 * *
1457 * Function: lld_groups_save_rights *
1458 * *
1459 * Parameters: groups - [IN] list of new groups *
1460 * *
1461 ******************************************************************************/
lld_groups_save_rights(zbx_vector_ptr_t * groups)1462 static void lld_groups_save_rights(zbx_vector_ptr_t *groups)
1463 {
1464 int i, j;
1465 DB_ROW row;
1466 DB_RESULT result;
1467 char *ptr, *name, *sql = NULL;
1468 size_t sql_alloc = 0, sql_offset = 0, offset;
1469 zbx_lld_group_t *group;
1470 zbx_vector_str_t group_names;
1471 zbx_vector_ptr_t group_rights;
1472 zbx_db_insert_t db_insert;
1473 zbx_lld_group_rights_t *rights, rights_local, *parent_rights;
1474 zbx_uint64_pair_t pair;
1475
1476 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1477
1478 zbx_vector_str_create(&group_names);
1479 zbx_vector_ptr_create(&group_rights);
1480
1481 /* make a list of direct parent group names and a list of new group rights */
1482 for (i = 0; i < groups->values_num; i++)
1483 {
1484 group = (zbx_lld_group_t *)groups->values[i];
1485
1486 if (NULL == (ptr = strrchr(group->name, '/')))
1487 continue;
1488
1489 lld_group_rights_append(&group_rights, group->name);
1490
1491 name = zbx_strdup(NULL, group->name);
1492 name[ptr - group->name] = '\0';
1493
1494 if (FAIL != zbx_vector_str_search(&group_names, name, ZBX_DEFAULT_STR_COMPARE_FUNC))
1495 {
1496 zbx_free(name);
1497 continue;
1498 }
1499
1500 zbx_vector_str_append(&group_names, name);
1501 }
1502
1503 if (0 == group_names.values_num)
1504 goto out;
1505
1506 /* read the parent group rights */
1507
1508 zbx_db_insert_prepare(&db_insert, "rights", "rightid", "id", "permission", "groupid", NULL);
1509 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1510 "select g.name,r.permission,r.groupid from hstgrp g,rights r"
1511 " where r.id=g.groupid"
1512 " and");
1513
1514 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "g.name", (const char **)group_names.values,
1515 group_names.values_num);
1516 result = DBselect("%s", sql);
1517
1518 while (NULL != (row = DBfetch(result)))
1519 {
1520 rights_local.name = row[0];
1521 if (FAIL == (i = zbx_vector_ptr_search(&group_rights, &rights_local, lld_group_rights_compare)))
1522 i = lld_group_rights_append(&group_rights, row[0]);
1523
1524 rights = (zbx_lld_group_rights_t *)group_rights.values[i];
1525 rights->prights = &rights->rights;
1526
1527 ZBX_STR2UINT64(pair.first, row[2]);
1528 pair.second = atoi(row[1]);
1529
1530 zbx_vector_uint64_pair_append(&rights->rights, pair);
1531 }
1532 DBfree_result(result);
1533
1534 zbx_vector_ptr_sort(&group_rights, lld_group_rights_compare);
1535
1536 /* assign rights for the new groups */
1537 for (i = 0; i < group_rights.values_num; i++)
1538 {
1539 rights = (zbx_lld_group_rights_t *)group_rights.values[i];
1540
1541 if (NULL != rights->prights)
1542 continue;
1543
1544 if (NULL == (ptr = strrchr(rights->name, '/')))
1545 continue;
1546
1547 offset = ptr - rights->name;
1548
1549 for (j = 0; j < i; j++)
1550 {
1551 parent_rights = (zbx_lld_group_rights_t *)group_rights.values[j];
1552
1553 if (strlen(parent_rights->name) != offset)
1554 continue;
1555
1556 if (0 != strncmp(parent_rights->name, rights->name, offset))
1557 continue;
1558
1559 rights->prights = parent_rights->prights;
1560 break;
1561 }
1562 }
1563
1564 /* save rights for the new groups */
1565 for (i = 0; i < groups->values_num; i++)
1566 {
1567 group = (zbx_lld_group_t *)groups->values[i];
1568
1569 rights_local.name = group->name;
1570 if (FAIL == (j = zbx_vector_ptr_bsearch(&group_rights, &rights_local, lld_group_rights_compare)))
1571 continue;
1572
1573 rights = (zbx_lld_group_rights_t *)group_rights.values[j];
1574
1575 if (NULL == rights->prights)
1576 continue;
1577
1578 for (j = 0; j < rights->prights->values_num; j++)
1579 {
1580 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), group->groupid,
1581 (int)rights->prights->values[j].second, rights->prights->values[j].first);
1582 }
1583 }
1584
1585 zbx_db_insert_autoincrement(&db_insert, "rightid");
1586 zbx_db_insert_execute(&db_insert);
1587 zbx_db_insert_clean(&db_insert);
1588
1589 zbx_free(sql);
1590 zbx_vector_ptr_clear_ext(&group_rights, (zbx_clean_func_t)lld_group_rights_free);
1591 zbx_vector_str_clear_ext(&group_names, zbx_str_free);
1592 out:
1593 zbx_vector_ptr_destroy(&group_rights);
1594 zbx_vector_str_destroy(&group_names);
1595
1596 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1597 }
1598
1599 /******************************************************************************
1600 * *
1601 * Function: lld_groups_save *
1602 * *
1603 * Parameters: groups - [IN/OUT] list of groups; should be sorted *
1604 * by groupid *
1605 * group_prototypes - [IN] list of group prototypes; should be *
1606 * sorted by group_prototypeid *
1607 * *
1608 ******************************************************************************/
lld_groups_save(zbx_vector_ptr_t * groups,const zbx_vector_ptr_t * group_prototypes)1609 static void lld_groups_save(zbx_vector_ptr_t *groups, const zbx_vector_ptr_t *group_prototypes)
1610 {
1611 int i, j, upd_groups_num = 0;
1612 zbx_lld_group_t *group;
1613 const zbx_lld_group_prototype_t *group_prototype;
1614 zbx_lld_host_t *host;
1615 zbx_uint64_t groupid = 0;
1616 char *sql = NULL, *name_esc, *name_proto_esc;
1617 size_t sql_alloc = 0, sql_offset = 0;
1618 zbx_db_insert_t db_insert, db_insert_gdiscovery;
1619 zbx_vector_ptr_t new_groups;
1620 zbx_vector_uint64_t new_group_prototype_ids;
1621
1622 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1623
1624 zbx_vector_uint64_create(&new_group_prototype_ids);
1625
1626 for (i = 0; i < groups->values_num; i++)
1627 {
1628 group = (zbx_lld_group_t *)groups->values[i];
1629
1630 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1631 continue;
1632
1633 if (0 == group->groupid)
1634 zbx_vector_uint64_append(&new_group_prototype_ids, group->group_prototypeid);
1635 else if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE))
1636 upd_groups_num++;
1637 }
1638
1639 if (0 == new_group_prototype_ids.values_num && 0 == upd_groups_num)
1640 goto out;
1641
1642 DBbegin();
1643
1644 if (0 != new_group_prototype_ids.values_num)
1645 {
1646 if (SUCCEED != DBlock_group_prototypeids(&new_group_prototype_ids))
1647 {
1648 /* the host group prototype was removed while processing lld rule */
1649 DBrollback();
1650 goto out;
1651 }
1652
1653 groupid = DBget_maxid_num("hstgrp", new_group_prototype_ids.values_num);
1654
1655 zbx_db_insert_prepare(&db_insert, "hstgrp", "groupid", "name", "flags", NULL);
1656
1657 zbx_db_insert_prepare(&db_insert_gdiscovery, "group_discovery", "groupid", "parent_group_prototypeid",
1658 "name", NULL);
1659
1660 zbx_vector_ptr_create(&new_groups);
1661 }
1662
1663 if (0 != upd_groups_num)
1664 {
1665 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1666 }
1667
1668 for (i = 0; i < groups->values_num; i++)
1669 {
1670 group = (zbx_lld_group_t *)groups->values[i];
1671
1672 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
1673 continue;
1674
1675 if (0 == group->groupid)
1676 {
1677 group->groupid = groupid++;
1678
1679 zbx_db_insert_add_values(&db_insert, group->groupid, group->name,
1680 (int)ZBX_FLAG_DISCOVERY_CREATED);
1681
1682 if (FAIL != (j = zbx_vector_ptr_bsearch(group_prototypes, &group->group_prototypeid,
1683 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1684 {
1685 group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[j];
1686
1687 zbx_db_insert_add_values(&db_insert_gdiscovery, group->groupid,
1688 group->group_prototypeid, group_prototype->name);
1689 }
1690 else
1691 THIS_SHOULD_NEVER_HAPPEN;
1692
1693 for (j = 0; j < group->hosts.values_num; j++)
1694 {
1695 host = (zbx_lld_host_t *)group->hosts.values[j];
1696
1697 /* hosts will be linked to a new host groups */
1698 zbx_vector_uint64_append(&host->new_groupids, group->groupid);
1699 }
1700
1701 zbx_vector_ptr_append(&new_groups, group);
1702 }
1703 else
1704 {
1705 if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE))
1706 {
1707 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update hstgrp set ");
1708 if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1709 {
1710 name_esc = DBdyn_escape_string(group->name);
1711
1712 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "name='%s'", name_esc);
1713
1714 zbx_free(name_esc);
1715 }
1716 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1717 " where groupid=" ZBX_FS_UI64 ";\n", group->groupid);
1718 }
1719
1720 if (0 != (group->flags & ZBX_FLAG_LLD_GROUP_UPDATE_NAME))
1721 {
1722 if (FAIL != (j = zbx_vector_ptr_bsearch(group_prototypes, &group->group_prototypeid,
1723 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1724 {
1725 group_prototype = (zbx_lld_group_prototype_t *)group_prototypes->values[j];
1726
1727 name_proto_esc = DBdyn_escape_string(group_prototype->name);
1728
1729 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1730 "update group_discovery"
1731 " set name='%s'"
1732 " where groupid=" ZBX_FS_UI64 ";\n",
1733 name_proto_esc, group->groupid);
1734
1735 zbx_free(name_proto_esc);
1736 }
1737 else
1738 THIS_SHOULD_NEVER_HAPPEN;
1739 }
1740 }
1741 }
1742
1743 if (0 != upd_groups_num)
1744 {
1745 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1746 DBexecute("%s", sql);
1747 zbx_free(sql);
1748 }
1749
1750 if (0 != new_group_prototype_ids.values_num)
1751 {
1752 zbx_db_insert_execute(&db_insert);
1753 zbx_db_insert_clean(&db_insert);
1754
1755 zbx_db_insert_execute(&db_insert_gdiscovery);
1756 zbx_db_insert_clean(&db_insert_gdiscovery);
1757
1758 lld_groups_save_rights(&new_groups);
1759 zbx_vector_ptr_destroy(&new_groups);
1760 }
1761
1762 DBcommit();
1763 out:
1764 zbx_vector_uint64_destroy(&new_group_prototype_ids);
1765
1766 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1767 }
1768
1769 /******************************************************************************
1770 * *
1771 * Function: lld_masterhostmacros_get *
1772 * *
1773 * Purpose: retrieve list of host macros which should be present on the each *
1774 * discovered host *
1775 * *
1776 * Parameters: hostmacros - [OUT] list of host macros *
1777 * *
1778 ******************************************************************************/
lld_masterhostmacros_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * hostmacros)1779 static void lld_masterhostmacros_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *hostmacros)
1780 {
1781 DB_RESULT result;
1782 DB_ROW row;
1783 zbx_lld_hostmacro_t *hostmacro;
1784
1785 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1786
1787 result = DBselect(
1788 "select hm.macro,hm.value,hm.description,hm.type"
1789 " from hostmacro hm,items i"
1790 " where hm.hostid=i.hostid"
1791 " and i.itemid=" ZBX_FS_UI64,
1792 lld_ruleid);
1793
1794 while (NULL != (row = DBfetch(result)))
1795 {
1796 hostmacro = (zbx_lld_hostmacro_t *)zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1797
1798 hostmacro->macro = zbx_strdup(NULL, row[0]);
1799 hostmacro->value = zbx_strdup(NULL, row[1]);
1800 hostmacro->description = zbx_strdup(NULL, row[2]);
1801 ZBX_STR2UCHAR(hostmacro->type, row[3]);
1802
1803 zbx_vector_ptr_append(hostmacros, hostmacro);
1804 }
1805 DBfree_result(result);
1806
1807 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1808 }
1809
1810 /******************************************************************************
1811 * *
1812 * Function: macro_str_compare_func *
1813 * *
1814 * Purpose: compare the name of host macros for search in vector *
1815 * *
1816 * Parameters: d1 - [IN] first zbx_lld_hostmacro_t *
1817 * d2 - [IN] second zbx_lld_hostmacro_t *
1818 * *
1819 * Return value: 0 if name of macros are equal *
1820 * *
1821 ******************************************************************************/
macro_str_compare_func(const void * d1,const void * d2)1822 static int macro_str_compare_func(const void *d1, const void *d2)
1823 {
1824 const zbx_lld_hostmacro_t *hostmacro1 = *(const zbx_lld_hostmacro_t **)d1;
1825 const zbx_lld_hostmacro_t *hostmacro2 = *(const zbx_lld_hostmacro_t **)d2;
1826
1827 return strcmp(hostmacro1->macro, hostmacro2->macro);
1828 }
1829
1830 /******************************************************************************
1831 * *
1832 * Function: lld_hostmacros_get *
1833 * *
1834 * Purpose: retrieve list of host macros which should be present on the each *
1835 * discovered host *
1836 * *
1837 * Parameters: parent_hostid - [IN] host prototype id *
1838 * masterhostmacros - [IN] list of master host macros *
1839 * hostmacros - [OUT] list of host macros *
1840 * *
1841 ******************************************************************************/
lld_hostmacros_get(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * masterhostmacros,zbx_vector_ptr_t * hostmacros)1842 static void lld_hostmacros_get(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *masterhostmacros,
1843 zbx_vector_ptr_t *hostmacros)
1844 {
1845 DB_RESULT result;
1846 DB_ROW row;
1847 zbx_lld_hostmacro_t *hostmacro;
1848 int i;
1849
1850 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1851
1852 result = DBselect(
1853 "select hm.macro,hm.value,hm.description,hm.type"
1854 " from hostmacro hm"
1855 " where hm.hostid=" ZBX_FS_UI64,
1856 parent_hostid);
1857
1858 while (NULL != (row = DBfetch(result)))
1859 {
1860 hostmacro = (zbx_lld_hostmacro_t *)zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1861
1862 hostmacro->macro = zbx_strdup(NULL, row[0]);
1863 hostmacro->value = zbx_strdup(NULL, row[1]);
1864 hostmacro->description = zbx_strdup(NULL, row[2]);
1865 ZBX_STR2UCHAR(hostmacro->type, row[3]);
1866
1867 zbx_vector_ptr_append(hostmacros, hostmacro);
1868 }
1869 DBfree_result(result);
1870
1871 for (i = 0; i < masterhostmacros->values_num; i++)
1872 {
1873 const zbx_lld_hostmacro_t *masterhostmacro;
1874
1875 if (FAIL != zbx_vector_ptr_search(hostmacros, masterhostmacros->values[i], macro_str_compare_func))
1876 continue;
1877
1878 hostmacro = (zbx_lld_hostmacro_t *)zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1879
1880 masterhostmacro = (const zbx_lld_hostmacro_t *)masterhostmacros->values[i];
1881 hostmacro->macro = zbx_strdup(NULL, masterhostmacro->macro);
1882 hostmacro->value = zbx_strdup(NULL, masterhostmacro->value);
1883 hostmacro->description = zbx_strdup(NULL, masterhostmacro->description);
1884 hostmacro->type = masterhostmacro->type;
1885
1886 zbx_vector_ptr_append(hostmacros, hostmacro);
1887 }
1888
1889 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1890 }
1891
1892 /******************************************************************************
1893 * *
1894 * Function: lld_hostmacro_make *
1895 * *
1896 ******************************************************************************/
lld_hostmacro_make(zbx_vector_ptr_t * hostmacros,zbx_uint64_t hostmacroid,const char * macro,const char * value,const char * description,unsigned char type)1897 static void lld_hostmacro_make(zbx_vector_ptr_t *hostmacros, zbx_uint64_t hostmacroid, const char *macro,
1898 const char *value, const char *description, unsigned char type)
1899 {
1900 zbx_lld_hostmacro_t *hostmacro;
1901 int i;
1902
1903 for (i = 0; i < hostmacros->values_num; i++)
1904 {
1905 hostmacro = (zbx_lld_hostmacro_t *)hostmacros->values[i];
1906
1907 /* check if host macro has already been added */
1908 if (0 == hostmacro->hostmacroid && 0 == strcmp(hostmacro->macro, macro))
1909 {
1910 hostmacro->hostmacroid = hostmacroid;
1911 if (0 != strcmp(hostmacro->value, value))
1912 hostmacro->flags |= ZBX_FLAG_LLD_HOSTMACRO_UPDATE_VALUE;
1913 if (0 != strcmp(hostmacro->description, description))
1914 hostmacro->flags |= ZBX_FLAG_LLD_HOSTMACRO_UPDATE_DESCRIPTION;
1915 if (hostmacro->type != type)
1916 hostmacro->flags |= ZBX_FLAG_LLD_HOSTMACRO_UPDATE_TYPE;
1917 return;
1918 }
1919 }
1920
1921 /* host macro is present on the host but not in new list, it should be removed */
1922 hostmacro = (zbx_lld_hostmacro_t *)zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1923 hostmacro->hostmacroid = hostmacroid;
1924 hostmacro->macro = NULL;
1925 hostmacro->value = NULL;
1926 hostmacro->description = NULL;
1927 hostmacro->flags = ZBX_FLAG_LLD_HOSTMACRO_REMOVE;
1928
1929 zbx_vector_ptr_append(hostmacros, hostmacro);
1930 }
1931
1932 /******************************************************************************
1933 * *
1934 * Function: lld_hostmacros_make *
1935 * *
1936 * Parameters: hostmacros - [IN] list of host macros which *
1937 * should be present on the each *
1938 * discovered host *
1939 * hosts - [IN/OUT] list of hosts *
1940 * should be sorted by hostid *
1941 * del_hostmacroids - [OUT] list of host macros which should be *
1942 * deleted *
1943 * *
1944 ******************************************************************************/
lld_hostmacros_make(const zbx_vector_ptr_t * hostmacros,zbx_vector_ptr_t * hosts,const zbx_vector_ptr_t * lld_macros)1945 static void lld_hostmacros_make(const zbx_vector_ptr_t *hostmacros, zbx_vector_ptr_t *hosts,
1946 const zbx_vector_ptr_t *lld_macros)
1947 {
1948 DB_RESULT result;
1949 DB_ROW row;
1950 int i, j;
1951 zbx_vector_uint64_t hostids;
1952 zbx_uint64_t hostmacroid, hostid;
1953 zbx_lld_host_t *host;
1954 zbx_lld_hostmacro_t *hostmacro = NULL;
1955
1956 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1957
1958 zbx_vector_uint64_create(&hostids);
1959
1960 for (i = 0; i < hosts->values_num; i++)
1961 {
1962 host = (zbx_lld_host_t *)hosts->values[i];
1963
1964 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
1965 continue;
1966
1967 zbx_vector_ptr_reserve(&host->new_hostmacros, hostmacros->values_num);
1968 for (j = 0; j < hostmacros->values_num; j++)
1969 {
1970 hostmacro = (zbx_lld_hostmacro_t *)zbx_malloc(NULL, sizeof(zbx_lld_hostmacro_t));
1971
1972 hostmacro->hostmacroid = 0;
1973 hostmacro->macro = zbx_strdup(NULL, ((zbx_lld_hostmacro_t *)hostmacros->values[j])->macro);
1974 hostmacro->value = zbx_strdup(NULL, ((zbx_lld_hostmacro_t *)hostmacros->values[j])->value);
1975 hostmacro->type = ((zbx_lld_hostmacro_t *)hostmacros->values[j])->type;
1976 hostmacro->description = zbx_strdup(NULL,
1977 ((zbx_lld_hostmacro_t *)hostmacros->values[j])->description);
1978 hostmacro->flags = 0x00;
1979 substitute_lld_macros(&hostmacro->value, host->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1980 substitute_lld_macros(&hostmacro->description, host->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
1981
1982 zbx_vector_ptr_append(&host->new_hostmacros, hostmacro);
1983 }
1984
1985 if (0 != host->hostid)
1986 zbx_vector_uint64_append(&hostids, host->hostid);
1987 }
1988
1989 if (0 != hostids.values_num)
1990 {
1991 char *sql = NULL;
1992 size_t sql_alloc = 0, sql_offset = 0;
1993
1994 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1995 "select hostmacroid,hostid,macro,value,description,type"
1996 " from hostmacro"
1997 " where");
1998 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
1999
2000 result = DBselect("%s", sql);
2001
2002 zbx_free(sql);
2003
2004 while (NULL != (row = DBfetch(result)))
2005 {
2006 unsigned char type;
2007
2008 ZBX_STR2UINT64(hostid, row[1]);
2009
2010 if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2011 {
2012 THIS_SHOULD_NEVER_HAPPEN;
2013 continue;
2014 }
2015
2016 host = (zbx_lld_host_t *)hosts->values[i];
2017
2018 ZBX_STR2UINT64(hostmacroid, row[0]);
2019 ZBX_STR2UCHAR(type, row[5]);
2020
2021 lld_hostmacro_make(&host->new_hostmacros, hostmacroid, row[2], row[3], row[4], type);
2022 }
2023 DBfree_result(result);
2024 }
2025
2026 zbx_vector_uint64_destroy(&hostids);
2027
2028 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2029 }
2030
2031 /******************************************************************************
2032 * *
2033 * Function: lld_tags_get *
2034 * *
2035 * Purpose: retrieve list of host tags which should be present on the each *
2036 * discovered host *
2037 * *
2038 * Parameters: parent_hostid - [IN] host prototype id *
2039 * tags - [OUT] list of host tags *
2040 * *
2041 ******************************************************************************/
lld_proto_tags_get(zbx_uint64_t parent_hostid,zbx_vector_db_tag_ptr_t * tags)2042 static void lld_proto_tags_get(zbx_uint64_t parent_hostid, zbx_vector_db_tag_ptr_t *tags)
2043 {
2044 DB_RESULT result;
2045 DB_ROW row;
2046 zbx_db_tag_t *tag;
2047
2048 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2049
2050 result = DBselect(
2051 "select tag,value"
2052 " from host_tag"
2053 " where hostid=" ZBX_FS_UI64,
2054 parent_hostid);
2055
2056 while (NULL != (row = DBfetch(result)))
2057 {
2058 tag = (zbx_db_tag_t *)zbx_malloc(NULL, sizeof(zbx_db_tag_t));
2059
2060 tag->tag = zbx_strdup(NULL, row[0]);
2061 tag->value = zbx_strdup(NULL, row[1]);
2062
2063 zbx_vector_db_tag_ptr_append(tags, tag);
2064 }
2065 DBfree_result(result);
2066
2067 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2068 }
2069
2070 /******************************************************************************
2071 * *
2072 * Function: lld_tag_validate_field *
2073 * *
2074 * Purpose: validate host tag field *
2075 * *
2076 * Parameters: name - [IN] the field name (tag, value) *
2077 * field - [IN] the field value *
2078 * field_len - [IN] the field length *
2079 * info - [OUT] error information *
2080 * *
2081 ******************************************************************************/
lld_tag_validate_field(const char * name,const char * field,size_t field_len,char ** info)2082 static int lld_tag_validate_field(const char *name, const char *field, size_t field_len, char **info)
2083 {
2084 if (SUCCEED != zbx_is_utf8(field))
2085 {
2086 char *field_utf8;
2087
2088 field_utf8 = zbx_strdup(NULL, field);
2089 zbx_replace_invalid_utf8(field_utf8);
2090 *info = zbx_strdcatf(*info, "Cannot create host tag: %s \"%s\" has invalid UTF-8 sequence.\n",
2091 name, field_utf8);
2092 zbx_free(field_utf8);
2093 return FAIL;
2094 }
2095
2096 if (zbx_strlen_utf8(field) > field_len)
2097 {
2098 *info = zbx_strdcatf(*info, "Cannot create host tag: %s \"%128s...\" is too long.\n", name, field);
2099 return FAIL;
2100 }
2101
2102 return SUCCEED;
2103 }
2104
2105 /******************************************************************************
2106 * *
2107 * Function: lld_tag_validate *
2108 * *
2109 * Purpose: validate host tag *
2110 * *
2111 * Parameters: tags - [IN] the current host tags *
2112 * tags_num - [IN] the number of host tags *
2113 * name - [IN] the new tag name *
2114 * value - [IN] the new tag value *
2115 * info - [OUT] error information *
2116 * *
2117 ******************************************************************************/
lld_tag_validate(zbx_db_tag_t ** tags,int tags_num,const char * name,const char * value,char ** info)2118 static int lld_tag_validate(zbx_db_tag_t **tags, int tags_num, const char *name, const char *value, char **info)
2119 {
2120 int i;
2121
2122 if ('\0' == *name)
2123 {
2124 *info = zbx_strdcatf(*info, "Cannot create host tag: empty tag name.\n");
2125 return FAIL;
2126 }
2127
2128 if (SUCCEED != lld_tag_validate_field("name", name, TAG_NAME_LEN, info))
2129 return FAIL;
2130
2131 if (SUCCEED != lld_tag_validate_field("value", value, TAG_VALUE_LEN, info))
2132 return FAIL;
2133
2134 for (i = 0; i < tags_num; i++)
2135 {
2136 if (0 == strcmp(tags[i]->tag, name) && 0 == strcmp(tags[i]->value, value))
2137 {
2138 *info = zbx_strdcatf(*info, "Cannot create host tag: tag \"%s\",\"%s\" already exists.\n",
2139 name, value);
2140
2141 return FAIL;
2142 }
2143 }
2144
2145 return SUCCEED;
2146 }
2147
2148 /******************************************************************************
2149 * *
2150 * Function: lld_host_update_tags *
2151 * *
2152 * Purpose: update host tags *
2153 * *
2154 * Parameters: host - [IN] a host with existing tags, sorted by tag + *
2155 * value. *
2156 * - [OUT] a host with updated tags, sorted by tagid *
2157 * tags - [IN] the new tags, sorted by tag + value *
2158 * lld_macros - [IN] a vector of LLD macros *
2159 * info - [OUT] error information *
2160 * *
2161 * Comments: No database changes are made if host tags are equal to the new *
2162 * tags. Otherwise the tags are updated starting with the first not *
2163 * matching tag. If there are more host tags than new tags then the *
2164 * extra host tags are marked for removal. If there are more new *
2165 * tags than host tags, then new tags are appended to the host tags.*
2166 * *
2167 ******************************************************************************/
lld_host_update_tags(zbx_lld_host_t * host,const zbx_vector_db_tag_ptr_t * tags,const zbx_vector_ptr_t * lld_macros,char ** info)2168 static void lld_host_update_tags(zbx_lld_host_t *host, const zbx_vector_db_tag_ptr_t *tags,
2169 const zbx_vector_ptr_t *lld_macros, char **info)
2170 {
2171 int i;
2172 zbx_db_tag_t *host_tag, *proto_tag;
2173 zbx_vector_db_tag_ptr_t new_tags;
2174 char *tag = NULL, *value = NULL;
2175
2176 zbx_vector_db_tag_ptr_create(&new_tags);
2177
2178 /* create vector of new tags with expanded lld macros */
2179 for (i = 0; i < tags->values_num; i++)
2180 {
2181 proto_tag = (zbx_db_tag_t *)tags->values[i];
2182
2183 tag = zbx_strdup(tag, proto_tag->tag);
2184 value = zbx_strdup(value, proto_tag->value);
2185 substitute_lld_macros(&tag, host->jp_row, lld_macros, ZBX_MACRO_FUNC, NULL, 0);
2186 substitute_lld_macros(&value, host->jp_row, lld_macros, ZBX_MACRO_FUNC, NULL, 0);
2187
2188 if (SUCCEED != lld_tag_validate(new_tags.values, new_tags.values_num, tag, value, info))
2189 continue;
2190
2191 proto_tag = (zbx_db_tag_t *)zbx_malloc(NULL, sizeof(zbx_db_tag_t));
2192 proto_tag->tag = tag;
2193 proto_tag->value = value;
2194 zbx_vector_db_tag_ptr_append(&new_tags, proto_tag);
2195
2196 tag = NULL;
2197 value = NULL;
2198 }
2199
2200 zbx_vector_db_tag_ptr_sort(&new_tags, zbx_db_tag_compare_func);
2201
2202 zbx_vector_db_tag_ptr_reserve(&host->tags, new_tags.values_num);
2203
2204 /* update host tags or flag them for removal */
2205 for (i = 0; i < host->tags.values_num; i++)
2206 {
2207 host_tag = (zbx_db_tag_t *)host->tags.values[i];
2208 if (i < new_tags.values_num)
2209 {
2210 proto_tag = (zbx_db_tag_t *)new_tags.values[i];
2211
2212 if (0 != strcmp(host_tag->tag, proto_tag->tag))
2213 {
2214 host_tag->tag = zbx_strdup(host_tag->tag, proto_tag->tag);
2215 host_tag->flags |= ZBX_FLAG_DB_TAG_UPDATE_TAG;
2216 }
2217
2218 if (0 != strcmp(host_tag->value, proto_tag->value))
2219 {
2220 host_tag->value = zbx_strdup(host_tag->value, proto_tag->value);
2221 host_tag->flags |= ZBX_FLAG_DB_TAG_UPDATE_VALUE;
2222 }
2223 }
2224 else
2225 host_tag->flags = ZBX_FLAG_DB_TAG_REMOVE;
2226 }
2227
2228 /* add missing tags */
2229 if (i < new_tags.values_num)
2230 {
2231 int j;
2232
2233 /* set uninitialized properties of new tags that will be moved to host */
2234 for (j = i; j < new_tags.values_num; j++)
2235 {
2236 proto_tag = (zbx_db_tag_t *)new_tags.values[j];
2237 proto_tag->tagid = 0;
2238 proto_tag->flags = 0;
2239 }
2240
2241 zbx_vector_db_tag_ptr_append_array(&host->tags, new_tags.values + i, new_tags.values_num - i);
2242 new_tags.values_num = i;
2243 }
2244
2245 zbx_free(tag);
2246 zbx_free(value);
2247
2248 /* sort existing tags by their ids for update operations */
2249 zbx_vector_db_tag_ptr_sort(&host->tags, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2250
2251 zbx_vector_db_tag_ptr_clear_ext(&new_tags, zbx_db_tag_free);
2252 zbx_vector_db_tag_ptr_destroy(&new_tags);
2253 }
2254
2255 /******************************************************************************
2256 * *
2257 * Function: lld_templates_make *
2258 * *
2259 * Purpose: gets templates from a host prototype *
2260 * *
2261 * Parameters: parent_hostid - [IN] host prototype identifier *
2262 * hosts - [IN/OUT] list of hosts *
2263 * should be sorted by hostid *
2264 * *
2265 ******************************************************************************/
lld_templates_make(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts)2266 static void lld_templates_make(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts)
2267 {
2268 DB_RESULT result;
2269 DB_ROW row;
2270 zbx_vector_uint64_t templateids, hostids;
2271 zbx_uint64_t templateid, hostid;
2272 zbx_lld_host_t *host;
2273 int i, j;
2274
2275 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2276
2277 zbx_vector_uint64_create(&templateids);
2278 zbx_vector_uint64_create(&hostids);
2279
2280 /* select templates which should be linked */
2281
2282 result = DBselect("select templateid from hosts_templates where hostid=" ZBX_FS_UI64, parent_hostid);
2283
2284 while (NULL != (row = DBfetch(result)))
2285 {
2286 ZBX_STR2UINT64(templateid, row[0]);
2287 zbx_vector_uint64_append(&templateids, templateid);
2288 }
2289 DBfree_result(result);
2290
2291 zbx_vector_uint64_sort(&templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2292
2293 /* select list of already created hosts */
2294
2295 for (i = 0; i < hosts->values_num; i++)
2296 {
2297 host = (zbx_lld_host_t *)hosts->values[i];
2298
2299 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2300 continue;
2301
2302 zbx_vector_uint64_reserve(&host->lnk_templateids, templateids.values_num);
2303 for (j = 0; j < templateids.values_num; j++)
2304 zbx_vector_uint64_append(&host->lnk_templateids, templateids.values[j]);
2305
2306 /* sort templates which should be linked by override */
2307 zbx_vector_uint64_sort(&host->lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2308 zbx_vector_uint64_uniq(&host->lnk_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2309
2310 if (0 != host->hostid)
2311 zbx_vector_uint64_append(&hostids, host->hostid);
2312 }
2313
2314 if (0 != hostids.values_num)
2315 {
2316 char *sql = NULL;
2317 size_t sql_alloc = 0, sql_offset = 0;
2318
2319 /* select already linked temlates */
2320
2321 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
2322 "select hostid,templateid"
2323 " from hosts_templates"
2324 " where");
2325 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
2326
2327 result = DBselect("%s", sql);
2328
2329 zbx_free(sql);
2330
2331 while (NULL != (row = DBfetch(result)))
2332 {
2333 ZBX_STR2UINT64(hostid, row[0]);
2334 ZBX_STR2UINT64(templateid, row[1]);
2335
2336 if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2337 {
2338 THIS_SHOULD_NEVER_HAPPEN;
2339 continue;
2340 }
2341
2342 host = (zbx_lld_host_t *)hosts->values[i];
2343
2344 if (FAIL == (i = zbx_vector_uint64_bsearch(&host->lnk_templateids, templateid,
2345 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2346 {
2347 /* templates which should be unlinked */
2348 zbx_vector_uint64_append(&host->del_templateids, templateid);
2349 }
2350 else
2351 {
2352 /* templates which are already linked */
2353 zbx_vector_uint64_remove(&host->lnk_templateids, i);
2354 }
2355 }
2356 DBfree_result(result);
2357
2358 for (i = 0; i < hosts->values_num; i++)
2359 {
2360 host = (zbx_lld_host_t *)hosts->values[i];
2361
2362 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2363 continue;
2364
2365 zbx_vector_uint64_sort(&host->del_templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2366 }
2367 }
2368
2369 zbx_vector_uint64_destroy(&hostids);
2370 zbx_vector_uint64_destroy(&templateids);
2371
2372 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
2373 }
2374
2375 /******************************************************************************
2376 * *
2377 * Function: lld_interface_snmp_prepare_sql *
2378 * *
2379 * Purpose: prepare sql for update record of interface_snmp table *
2380 * *
2381 * Parameters: interfaceid - [IN] snmp interface id; *
2382 * snmp - [IN] snmp values for update *
2383 * sql - [IN/OUT] sql string *
2384 * sql_alloc - [IN/OUT] size of sql string *
2385 * sql_offset - [IN/OUT] offset in sql string *
2386 * *
2387 ******************************************************************************/
lld_interface_snmp_prepare_sql(const zbx_uint64_t interfaceid,const zbx_lld_interface_snmp_t * snmp,char ** sql,size_t * sql_alloc,size_t * sql_offset)2388 static void lld_interface_snmp_prepare_sql(const zbx_uint64_t interfaceid, const zbx_lld_interface_snmp_t *snmp,
2389 char **sql, size_t *sql_alloc, size_t *sql_offset)
2390 {
2391 const char *d = "";
2392 char *value_esc;
2393
2394 zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "update interface_snmp set ");
2395
2396 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_TYPE))
2397 {
2398 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "version=%d", (int)snmp->version);
2399 d = ",";
2400 }
2401
2402 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_BULK))
2403 {
2404 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sbulk=%d", d, (int)snmp->bulk);
2405 d = ",";
2406 }
2407
2408 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_COMMUNITY))
2409 {
2410 value_esc = DBdyn_escape_string(snmp->community);
2411 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%scommunity='%s'", d, value_esc);
2412 zbx_free(value_esc);
2413 d = ",";
2414 }
2415
2416 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECNAME))
2417 {
2418 value_esc = DBdyn_escape_string(snmp->securityname);
2419 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssecurityname='%s'", d, value_esc);
2420 zbx_free(value_esc);
2421 d = ",";
2422 }
2423
2424 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECLEVEL))
2425 {
2426 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssecuritylevel=%d", d, (int)snmp->securitylevel);
2427 d = ",";
2428 }
2429
2430 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPASS))
2431 {
2432 value_esc = DBdyn_escape_string(snmp->authpassphrase);
2433 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sauthpassphrase='%s'", d, value_esc);
2434 zbx_free(value_esc);
2435 d = ",";
2436 }
2437
2438 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPASS))
2439 {
2440 value_esc = DBdyn_escape_string(snmp->privpassphrase);
2441 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sprivpassphrase='%s'", d, value_esc);
2442 zbx_free(value_esc);
2443 d = ",";
2444 }
2445
2446 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPROTOCOL))
2447 {
2448 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sauthprotocol=%d", d, (int)snmp->authprotocol);
2449 d = ",";
2450 }
2451
2452 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPROTOCOL))
2453 {
2454 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sprivprotocol=%d", d, (int)snmp->privprotocol);
2455 d = ",";
2456 }
2457
2458 if (0 != (snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_CONTEXT))
2459 {
2460 value_esc = DBdyn_escape_string(snmp->contextname);
2461 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%scontextname='%s'", d, value_esc);
2462 zbx_free(value_esc);
2463 }
2464
2465 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, " where interfaceid=" ZBX_FS_UI64 ";\n", interfaceid);
2466 }
2467
2468 /******************************************************************************
2469 * *
2470 * Function: lld_hosts_save *
2471 * *
2472 * Parameters: parent_hostid - [IN] parent host id *
2473 * hosts - [IN] list of hosts; *
2474 * host_proto - [IN] host proto *
2475 * proxy_hostid - [IN] proxy host id *
2476 * ipmi_authtype - [IN] ipmi authtype *
2477 * ipmi_privilege - [IN] ipmi privilege *
2478 * ipmi_username - [IN] ipmi username *
2479 * ipmi_password - [IN] ipmi password *
2480 * status - [IN] host status *
2481 * inventory_mode - [IN] host inventory mode *
2482 * tls_connect - [IN] tls connect *
2483 * tls_accept - [IN] tls accept *
2484 * tls_issuer - [IN] tls cert issuer *
2485 * tls_subject - [IN] tls cert subject *
2486 * tls_psk_identity - [IN] tls psk identity *
2487 * tls_psk - [IN] tls psk *
2488 * del_hostgroupids - [IN] host groups which should be deleted *
2489 * *
2490 ******************************************************************************/
lld_hosts_save(zbx_uint64_t parent_hostid,zbx_vector_ptr_t * hosts,const char * host_proto,zbx_uint64_t proxy_hostid,char ipmi_authtype,unsigned char ipmi_privilege,const char * ipmi_username,const char * ipmi_password,unsigned char tls_connect,unsigned char tls_accept,const char * tls_issuer,const char * tls_subject,const char * tls_psk_identity,const char * tls_psk,const zbx_vector_uint64_t * del_hostgroupids)2491 static void lld_hosts_save(zbx_uint64_t parent_hostid, zbx_vector_ptr_t *hosts, const char *host_proto,
2492 zbx_uint64_t proxy_hostid, char ipmi_authtype, unsigned char ipmi_privilege, const char *ipmi_username,
2493 const char *ipmi_password, unsigned char tls_connect,
2494 unsigned char tls_accept, const char *tls_issuer, const char *tls_subject, const char *tls_psk_identity,
2495 const char *tls_psk, const zbx_vector_uint64_t *del_hostgroupids)
2496 {
2497 int i, j, new_hosts = 0, new_host_inventories = 0, upd_hosts = 0, new_hostgroups = 0,
2498 new_hostmacros = 0, upd_hostmacros = 0, new_interfaces = 0, upd_interfaces = 0,
2499 new_snmp = 0, upd_snmp = 0, new_tags = 0, upd_tags = 0;
2500 zbx_lld_host_t *host;
2501 zbx_lld_hostmacro_t *hostmacro;
2502 zbx_lld_interface_t *interface;
2503 zbx_vector_uint64_t upd_manual_host_inventory_hostids, upd_auto_host_inventory_hostids,
2504 del_host_inventory_hostids, del_interfaceids,
2505 del_snmp_ids, del_hostmacroids, del_tagids;
2506 zbx_uint64_t hostid = 0, hostgroupid = 0, hostmacroid = 0, interfaceid = 0;
2507 char *sql1 = NULL, *sql2 = NULL, *value_esc;
2508 size_t sql1_alloc = 0, sql1_offset = 0,
2509 sql2_alloc = 0, sql2_offset = 0;
2510 zbx_db_insert_t db_insert, db_insert_hdiscovery, db_insert_hinventory, db_insert_hgroups,
2511 db_insert_hmacro, db_insert_interface, db_insert_idiscovery, db_insert_snmp,
2512 db_insert_tag;
2513
2514 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
2515
2516 zbx_vector_uint64_create(&upd_manual_host_inventory_hostids);
2517 zbx_vector_uint64_create(&upd_auto_host_inventory_hostids);
2518 zbx_vector_uint64_create(&del_host_inventory_hostids);
2519 zbx_vector_uint64_create(&del_interfaceids);
2520 zbx_vector_uint64_create(&del_hostmacroids);
2521 zbx_vector_uint64_create(&del_snmp_ids);
2522 zbx_vector_uint64_create(&del_tagids);
2523
2524 for (i = 0; i < hosts->values_num; i++)
2525 {
2526 host = (zbx_lld_host_t *)hosts->values[i];
2527
2528 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2529 continue;
2530
2531 if (0 == host->hostid)
2532 {
2533 new_hosts++;
2534 if (HOST_INVENTORY_DISABLED != host->inventory_mode)
2535 new_host_inventories++;
2536 }
2537 else
2538 {
2539 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE))
2540 upd_hosts++;
2541
2542 if (host->inventory_mode_orig != host->inventory_mode)
2543 {
2544 if (HOST_INVENTORY_DISABLED == host->inventory_mode)
2545 zbx_vector_uint64_append(&del_host_inventory_hostids, host->hostid);
2546 else if (HOST_INVENTORY_DISABLED == host->inventory_mode_orig)
2547 new_host_inventories++;
2548 else
2549 {
2550 switch (host->inventory_mode)
2551 {
2552 case HOST_INVENTORY_MANUAL:
2553 zbx_vector_uint64_append(&upd_manual_host_inventory_hostids,
2554 host->hostid);
2555 break;
2556 case HOST_INVENTORY_AUTOMATIC:
2557 zbx_vector_uint64_append(&upd_auto_host_inventory_hostids,
2558 host->hostid);
2559 break;
2560 }
2561 }
2562 }
2563 }
2564
2565 new_hostgroups += host->new_groupids.values_num;
2566
2567 for (j = 0; j < host->interfaces.values_num; j++)
2568 {
2569 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2570
2571 if (0 == interface->interfaceid)
2572 new_interfaces++;
2573 else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE))
2574 upd_interfaces++;
2575 else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
2576 zbx_vector_uint64_append(&del_interfaceids, interface->interfaceid);
2577
2578 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_REMOVE))
2579 zbx_vector_uint64_append(&del_snmp_ids, interface->interfaceid);
2580
2581 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_DATA_EXISTS))
2582 {
2583 if (0 == interface->interfaceid)
2584 interface->data.snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_CREATE;
2585
2586 if (0 != (interface->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_CREATE))
2587 new_snmp++;
2588 else if (0 != (interface->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE))
2589 upd_snmp++;
2590 }
2591 }
2592
2593 for (j = 0; j < host->new_hostmacros.values_num; j++)
2594 {
2595 hostmacro = (zbx_lld_hostmacro_t *)host->new_hostmacros.values[j];
2596
2597 if (0 == hostmacro->hostmacroid)
2598 new_hostmacros++;
2599 else if (0 != (hostmacro->flags & ZBX_FLAG_LLD_HOSTMACRO_UPDATE))
2600 upd_hostmacros++;
2601 else if (0 != (hostmacro->flags & ZBX_FLAG_LLD_HOSTMACRO_REMOVE))
2602 zbx_vector_uint64_append(&del_hostmacroids, hostmacro->hostmacroid);
2603 }
2604
2605 for (j = 0; j < host->tags.values_num; j++)
2606 {
2607 if (0 == host->tags.values[j]->tagid)
2608 new_tags++;
2609 else if (0 != (host->tags.values[j]->flags & ZBX_FLAG_DB_TAG_UPDATE))
2610 upd_tags++;
2611 else if (0 != (host->tags.values[j]->flags & ZBX_FLAG_DB_TAG_REMOVE))
2612 zbx_vector_uint64_append(&del_tagids, host->tags.values[j]->tagid);
2613 }
2614 }
2615
2616 if (0 == new_hosts && 0 == new_host_inventories && 0 == upd_hosts && 0 == upd_interfaces &&
2617 0 == upd_hostmacros && 0 == new_hostgroups && 0 == new_hostmacros && 0 == new_interfaces &&
2618 0 == del_hostgroupids->values_num && 0 == del_hostmacroids.values_num &&
2619 0 == upd_auto_host_inventory_hostids.values_num &&
2620 0 == upd_manual_host_inventory_hostids.values_num &&
2621 0 == del_host_inventory_hostids.values_num && 0 == del_interfaceids.values_num &&
2622 0 == new_snmp && 0 == upd_snmp && 0 == del_snmp_ids.values_num &&
2623 0 == new_tags && 0 == upd_tags && 0 == del_tagids.values_num)
2624 {
2625 goto out;
2626 }
2627
2628 DBbegin();
2629
2630 if (SUCCEED != DBlock_hostid(parent_hostid))
2631 {
2632 /* the host prototype was removed while processing lld rule */
2633 DBrollback();
2634 goto out;
2635 }
2636
2637 if (0 != new_hosts)
2638 {
2639 hostid = DBget_maxid_num("hosts", new_hosts);
2640
2641 zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "host", "name", "proxy_hostid", "ipmi_authtype",
2642 "ipmi_privilege", "ipmi_username", "ipmi_password", "status", "flags", "tls_connect",
2643 "tls_accept", "tls_issuer", "tls_subject", "tls_psk_identity", "tls_psk",
2644 "custom_interfaces", NULL);
2645
2646 zbx_db_insert_prepare(&db_insert_hdiscovery, "host_discovery", "hostid", "parent_hostid", "host", NULL);
2647 }
2648
2649 if (0 != new_host_inventories)
2650 {
2651 zbx_db_insert_prepare(&db_insert_hinventory, "host_inventory", "hostid", "inventory_mode", NULL);
2652 }
2653
2654 if (0 != upd_hosts || 0 != upd_interfaces || 0 != upd_snmp || 0 != upd_hostmacros || 0 != upd_tags)
2655 {
2656 DBbegin_multiple_update(&sql1, &sql1_alloc, &sql1_offset);
2657 }
2658
2659 if (0 != new_hostgroups)
2660 {
2661 hostgroupid = DBget_maxid_num("hosts_groups", new_hostgroups);
2662
2663 zbx_db_insert_prepare(&db_insert_hgroups, "hosts_groups", "hostgroupid", "hostid", "groupid", NULL);
2664 }
2665
2666 if (0 != new_hostmacros)
2667 {
2668 hostmacroid = DBget_maxid_num("hostmacro", new_hostmacros);
2669
2670 zbx_db_insert_prepare(&db_insert_hmacro, "hostmacro", "hostmacroid", "hostid", "macro", "value",
2671 "description", "type", NULL);
2672 }
2673
2674 if (0 != new_interfaces)
2675 {
2676 interfaceid = DBget_maxid_num("interface", new_interfaces);
2677
2678 zbx_db_insert_prepare(&db_insert_interface, "interface", "interfaceid", "hostid", "type", "main",
2679 "useip", "ip", "dns", "port", NULL);
2680
2681 zbx_db_insert_prepare(&db_insert_idiscovery, "interface_discovery", "interfaceid",
2682 "parent_interfaceid", NULL);
2683 }
2684
2685 if (0 != new_snmp)
2686 {
2687 zbx_db_insert_prepare(&db_insert_snmp, "interface_snmp", "interfaceid", "version", "bulk", "community",
2688 "securityname", "securitylevel", "authpassphrase", "privpassphrase", "authprotocol",
2689 "privprotocol", "contextname", NULL);
2690 }
2691
2692 if (0 != new_tags)
2693 zbx_db_insert_prepare(&db_insert_tag, "host_tag", "hosttagid", "hostid", "tag", "value", NULL);
2694
2695 for (i = 0; i < hosts->values_num; i++)
2696 {
2697 host = (zbx_lld_host_t *)hosts->values[i];
2698
2699 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
2700 continue;
2701
2702 if (0 == host->hostid)
2703 {
2704 host->hostid = hostid++;
2705
2706 zbx_db_insert_add_values(&db_insert, host->hostid, host->host, host->name, proxy_hostid,
2707 (int)ipmi_authtype, (int)ipmi_privilege, ipmi_username, ipmi_password,
2708 (int)host->status, (int)ZBX_FLAG_DISCOVERY_CREATED, (int)tls_connect,
2709 (int)tls_accept, tls_issuer, tls_subject, tls_psk_identity, tls_psk,
2710 host->custom_interfaces);
2711
2712 zbx_db_insert_add_values(&db_insert_hdiscovery, host->hostid, parent_hostid, host_proto);
2713
2714 if (HOST_INVENTORY_DISABLED != host->inventory_mode)
2715 zbx_db_insert_add_values(&db_insert_hinventory, host->hostid, (int)host->inventory_mode);
2716 }
2717 else
2718 {
2719 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE))
2720 {
2721 const char *d = "";
2722
2723 zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update hosts set ");
2724 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
2725 {
2726 value_esc = DBdyn_escape_string(host->host);
2727
2728 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "host='%s'", value_esc);
2729 d = ",";
2730
2731 zbx_free(value_esc);
2732 }
2733 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_NAME))
2734 {
2735 value_esc = DBdyn_escape_string(host->name);
2736
2737 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2738 "%sname='%s'", d, value_esc);
2739 d = ",";
2740
2741 zbx_free(value_esc);
2742 }
2743 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_PROXY))
2744 {
2745 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2746 "%sproxy_hostid=%s", d, DBsql_id_ins(proxy_hostid));
2747 d = ",";
2748 }
2749 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_AUTH))
2750 {
2751 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2752 "%sipmi_authtype=%d", d, (int)ipmi_authtype);
2753 d = ",";
2754 }
2755 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PRIV))
2756 {
2757 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2758 "%sipmi_privilege=%d", d, (int)ipmi_privilege);
2759 d = ",";
2760 }
2761 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_USER))
2762 {
2763 value_esc = DBdyn_escape_string(ipmi_username);
2764
2765 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2766 "%sipmi_username='%s'", d, value_esc);
2767 d = ",";
2768
2769 zbx_free(value_esc);
2770 }
2771 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_IPMI_PASS))
2772 {
2773 value_esc = DBdyn_escape_string(ipmi_password);
2774
2775 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2776 "%sipmi_password='%s'", d, value_esc);
2777 d = ",";
2778
2779 zbx_free(value_esc);
2780 }
2781 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_CONNECT))
2782 {
2783 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2784 "%stls_connect=%d", d, tls_connect);
2785 d = ",";
2786 }
2787 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_ACCEPT))
2788 {
2789 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2790 "%stls_accept=%d", d, tls_accept);
2791 d = ",";
2792 }
2793 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_ISSUER))
2794 {
2795 value_esc = DBdyn_escape_string(tls_issuer);
2796
2797 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2798 "%stls_issuer='%s'", d, value_esc);
2799 d = ",";
2800
2801 zbx_free(value_esc);
2802 }
2803 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_SUBJECT))
2804 {
2805 value_esc = DBdyn_escape_string(tls_subject);
2806
2807 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2808 "%stls_subject='%s'", d, value_esc);
2809 d = ",";
2810
2811 zbx_free(value_esc);
2812 }
2813 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK_IDENTITY))
2814 {
2815 value_esc = DBdyn_escape_string(tls_psk_identity);
2816
2817 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2818 "%stls_psk_identity='%s'", d, value_esc);
2819 d = ",";
2820
2821 zbx_free(value_esc);
2822 }
2823 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_TLS_PSK))
2824 {
2825 value_esc = DBdyn_escape_string(tls_psk);
2826
2827 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2828 "%stls_psk='%s'", d, value_esc);
2829 d = ",";
2830
2831 zbx_free(value_esc);
2832 }
2833 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_CUSTOM_INTERFACES))
2834 {
2835 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2836 "%scustom_interfaces=%d", d, (int)host->custom_interfaces);
2837 }
2838 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, " where hostid=" ZBX_FS_UI64 ";\n",
2839 host->hostid);
2840 }
2841
2842 if (host->inventory_mode_orig != host->inventory_mode &&
2843 HOST_INVENTORY_DISABLED == host->inventory_mode_orig)
2844 {
2845 zbx_db_insert_add_values(&db_insert_hinventory, host->hostid, (int)host->inventory_mode);
2846 }
2847
2848 if (0 != (host->flags & ZBX_FLAG_LLD_HOST_UPDATE_HOST))
2849 {
2850 value_esc = DBdyn_escape_string(host_proto);
2851
2852 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2853 "update host_discovery"
2854 " set host='%s'"
2855 " where hostid=" ZBX_FS_UI64 ";\n",
2856 value_esc, host->hostid);
2857
2858 zbx_free(value_esc);
2859 }
2860 }
2861
2862 for (j = 0; j < host->interfaces.values_num; j++)
2863 {
2864 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
2865
2866 if (0 == interface->interfaceid)
2867 {
2868 interface->interfaceid = interfaceid++;
2869
2870 zbx_db_insert_add_values(&db_insert_interface, interface->interfaceid, host->hostid,
2871 (int)interface->type, (int)interface->main, (int)interface->useip,
2872 interface->ip, interface->dns, interface->port);
2873
2874 zbx_db_insert_add_values(&db_insert_idiscovery, interface->interfaceid,
2875 interface->parent_interfaceid);
2876 }
2877 else if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE))
2878 {
2879 const char *d = "";
2880
2881 zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update interface set ");
2882 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
2883 {
2884 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "type=%d",
2885 (int)interface->type);
2886 d = ",";
2887 }
2888 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN))
2889 {
2890 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%smain=%d",
2891 d, (int)interface->main);
2892 d = ",";
2893 }
2894 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP))
2895 {
2896 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%suseip=%d",
2897 d, (int)interface->useip);
2898 d = ",";
2899 }
2900 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_IP))
2901 {
2902 value_esc = DBdyn_escape_string(interface->ip);
2903 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sip='%s'", d, value_esc);
2904 zbx_free(value_esc);
2905 d = ",";
2906 }
2907 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS))
2908 {
2909 value_esc = DBdyn_escape_string(interface->dns);
2910 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sdns='%s'", d, value_esc);
2911 zbx_free(value_esc);
2912 d = ",";
2913 }
2914 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT))
2915 {
2916 value_esc = DBdyn_escape_string(interface->port);
2917 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sport='%s'",
2918 d, value_esc);
2919 zbx_free(value_esc);
2920 }
2921 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2922 " where interfaceid=" ZBX_FS_UI64 ";\n", interface->interfaceid);
2923 }
2924
2925 if (0 != (interface->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_DATA_EXISTS))
2926 {
2927 if (0 != (interface->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_CREATE))
2928 {
2929 zbx_db_insert_add_values(&db_insert_snmp, interface->interfaceid,
2930 (int)interface->data.snmp->version,
2931 (int)interface->data.snmp->bulk,
2932 interface->data.snmp->community,
2933 interface->data.snmp->securityname,
2934 (int)interface->data.snmp->securitylevel,
2935 interface->data.snmp->authpassphrase,
2936 interface->data.snmp->privpassphrase,
2937 (int)interface->data.snmp->authprotocol,
2938 (int)interface->data.snmp->privprotocol,
2939 interface->data.snmp->contextname);
2940 }
2941 else if (0 != (interface->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE))
2942 {
2943 lld_interface_snmp_prepare_sql(interface->interfaceid, interface->data.snmp,
2944 &sql1, &sql1_alloc, &sql1_offset);
2945 }
2946 }
2947 }
2948
2949 for (j = 0; j < host->new_groupids.values_num; j++)
2950 {
2951 zbx_db_insert_add_values(&db_insert_hgroups, hostgroupid++, host->hostid,
2952 host->new_groupids.values[j]);
2953 }
2954
2955 for (j = 0; j < host->new_hostmacros.values_num; j++)
2956 {
2957 hostmacro = (zbx_lld_hostmacro_t *)host->new_hostmacros.values[j];
2958
2959 if (0 == hostmacro->hostmacroid)
2960 {
2961 zbx_db_insert_add_values(&db_insert_hmacro, hostmacroid++, host->hostid,
2962 hostmacro->macro, hostmacro->value, hostmacro->description,
2963 (int)hostmacro->type);
2964 }
2965 else if (0 != (hostmacro->flags & ZBX_FLAG_LLD_HOSTMACRO_UPDATE))
2966 {
2967 const char *d = "";
2968
2969 zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update hostmacro set ");
2970 if (0 != (hostmacro->flags & ZBX_FLAG_LLD_HOSTMACRO_UPDATE_VALUE))
2971 {
2972 value_esc = DBdyn_escape_string(hostmacro->value);
2973 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "value='%s'", value_esc);
2974 zbx_free(value_esc);
2975 d = ",";
2976 }
2977 if (0 != (hostmacro->flags & ZBX_FLAG_LLD_HOSTMACRO_UPDATE_DESCRIPTION))
2978 {
2979 value_esc = DBdyn_escape_string(hostmacro->description);
2980 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sdescription='%s'",
2981 d, value_esc);
2982 zbx_free(value_esc);
2983 d = ",";
2984 }
2985 if (0 != (hostmacro->flags & ZBX_FLAG_LLD_HOSTMACRO_UPDATE_TYPE))
2986 {
2987 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%stype=%d",
2988 d, hostmacro->type);
2989 }
2990 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
2991 " where hostmacroid=" ZBX_FS_UI64 ";\n", hostmacro->hostmacroid);
2992 }
2993 }
2994
2995 for (j = 0; j < host->tags.values_num; j++)
2996 {
2997 zbx_db_tag_t *tag = host->tags.values[j];
2998
2999 if (0 == tag->tagid)
3000 {
3001 zbx_db_insert_add_values(&db_insert_tag, __UINT64_C(0), host->hostid, tag->tag,
3002 tag->value);
3003 }
3004 else if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE))
3005 {
3006 char delim = ' ';
3007
3008 zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update host_tag set");
3009
3010 if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE_TAG))
3011 {
3012 value_esc = DBdyn_escape_string(tag->tag);
3013 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%ctag='%s'", delim,
3014 value_esc);
3015 zbx_free(value_esc);
3016 delim = ',';
3017 }
3018
3019 if (0 != (tag->flags & ZBX_FLAG_DB_TAG_UPDATE_VALUE))
3020 {
3021 value_esc = DBdyn_escape_string(tag->value);
3022 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%cvalue='%s'", delim,
3023 value_esc);
3024 zbx_free(value_esc);
3025 }
3026
3027 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
3028 " where hosttagid=" ZBX_FS_UI64 ";\n", tag->tagid);
3029 }
3030 }
3031 }
3032
3033 if (0 != new_hosts)
3034 {
3035 zbx_db_insert_execute(&db_insert);
3036 zbx_db_insert_clean(&db_insert);
3037
3038 zbx_db_insert_execute(&db_insert_hdiscovery);
3039 zbx_db_insert_clean(&db_insert_hdiscovery);
3040 }
3041
3042 if (0 != new_host_inventories)
3043 {
3044 zbx_db_insert_execute(&db_insert_hinventory);
3045 zbx_db_insert_clean(&db_insert_hinventory);
3046 }
3047
3048 if (0 != new_hostgroups)
3049 {
3050 zbx_db_insert_execute(&db_insert_hgroups);
3051 zbx_db_insert_clean(&db_insert_hgroups);
3052 }
3053
3054 if (0 != new_hostmacros)
3055 {
3056 zbx_db_insert_execute(&db_insert_hmacro);
3057 zbx_db_insert_clean(&db_insert_hmacro);
3058 }
3059
3060 if (0 != new_interfaces)
3061 {
3062 zbx_db_insert_execute(&db_insert_interface);
3063 zbx_db_insert_clean(&db_insert_interface);
3064
3065 zbx_db_insert_execute(&db_insert_idiscovery);
3066 zbx_db_insert_clean(&db_insert_idiscovery);
3067 }
3068
3069 if (0 != new_snmp)
3070 {
3071 zbx_db_insert_execute(&db_insert_snmp);
3072 zbx_db_insert_clean(&db_insert_snmp);
3073 }
3074
3075 if (0 != new_tags)
3076 {
3077 zbx_db_insert_autoincrement(&db_insert_tag, "hosttagid");
3078 zbx_db_insert_execute(&db_insert_tag);
3079 zbx_db_insert_clean(&db_insert_tag);
3080 }
3081
3082 if (NULL != sql1)
3083 {
3084 DBend_multiple_update(&sql1, &sql1_alloc, &sql1_offset);
3085
3086 /* in ORACLE always present begin..end; */
3087 if (16 < sql1_offset)
3088 DBexecute("%s", sql1);
3089
3090 zbx_free(sql1);
3091 }
3092
3093 if (0 != del_hostgroupids->values_num || 0 != del_hostmacroids.values_num ||
3094 0 != upd_auto_host_inventory_hostids.values_num ||
3095 0 != upd_manual_host_inventory_hostids.values_num ||
3096 0 != del_host_inventory_hostids.values_num ||
3097 0 != del_interfaceids.values_num || 0 != del_snmp_ids.values_num || 0 != del_tagids.values_num)
3098 {
3099 DBbegin_multiple_update(&sql2, &sql2_alloc, &sql2_offset);
3100
3101 if (0 != del_hostgroupids->values_num)
3102 {
3103 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from hosts_groups where");
3104 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostgroupid",
3105 del_hostgroupids->values, del_hostgroupids->values_num);
3106 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
3107 }
3108
3109 if (0 != del_hostmacroids.values_num)
3110 {
3111 zbx_vector_uint64_sort(&del_hostmacroids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3112 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from hostmacro where");
3113 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostmacroid",
3114 del_hostmacroids.values, del_hostmacroids.values_num);
3115 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
3116 }
3117
3118 if (0 != upd_manual_host_inventory_hostids.values_num)
3119 {
3120 zbx_snprintf_alloc(&sql2, &sql2_alloc, &sql2_offset,
3121 "update host_inventory set inventory_mode=%d where", HOST_INVENTORY_MANUAL);
3122 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostid",
3123 upd_manual_host_inventory_hostids.values,
3124 upd_manual_host_inventory_hostids.values_num);
3125 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
3126 }
3127
3128 if (0 != upd_auto_host_inventory_hostids.values_num)
3129 {
3130 zbx_snprintf_alloc(&sql2, &sql2_alloc, &sql2_offset,
3131 "update host_inventory set inventory_mode=%d where", HOST_INVENTORY_AUTOMATIC);
3132 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostid",
3133 upd_auto_host_inventory_hostids.values,
3134 upd_auto_host_inventory_hostids.values_num);
3135 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
3136 }
3137
3138 if (0 != del_host_inventory_hostids.values_num)
3139 {
3140 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from host_inventory where");
3141 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hostid",
3142 del_host_inventory_hostids.values, del_host_inventory_hostids.values_num);
3143 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
3144 }
3145
3146 if (0 != del_snmp_ids.values_num)
3147 {
3148 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from interface_snmp where");
3149 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "interfaceid",
3150 del_snmp_ids.values, del_snmp_ids.values_num);
3151 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
3152 }
3153
3154 if (0 != del_interfaceids.values_num)
3155 {
3156 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from interface where");
3157 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "interfaceid",
3158 del_interfaceids.values, del_interfaceids.values_num);
3159 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
3160 }
3161
3162 if (0 != del_tagids.values_num)
3163 {
3164 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from host_tag where");
3165 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hosttagid", del_tagids.values,
3166 del_tagids.values_num);
3167 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n");
3168 }
3169
3170 DBend_multiple_update(&sql2, &sql2_alloc, &sql2_offset);
3171 DBexecute("%s", sql2);
3172 zbx_free(sql2);
3173 }
3174
3175 DBcommit();
3176 out:
3177 zbx_vector_uint64_destroy(&del_tagids);
3178 zbx_vector_uint64_destroy(&del_snmp_ids);
3179 zbx_vector_uint64_destroy(&del_interfaceids);
3180 zbx_vector_uint64_destroy(&del_hostmacroids);
3181 zbx_vector_uint64_destroy(&del_host_inventory_hostids);
3182 zbx_vector_uint64_destroy(&upd_auto_host_inventory_hostids);
3183 zbx_vector_uint64_destroy(&upd_manual_host_inventory_hostids);
3184
3185 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3186 }
3187
3188 /******************************************************************************
3189 * *
3190 * Function: lld_templates_link *
3191 * *
3192 ******************************************************************************/
lld_templates_link(const zbx_vector_ptr_t * hosts,char ** error)3193 static void lld_templates_link(const zbx_vector_ptr_t *hosts, char **error)
3194 {
3195 int i;
3196 zbx_lld_host_t *host;
3197 char *err = NULL;
3198
3199 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3200
3201 for (i = 0; i < hosts->values_num; i++)
3202 {
3203 host = (zbx_lld_host_t *)hosts->values[i];
3204
3205 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
3206 continue;
3207
3208 if (0 != host->del_templateids.values_num)
3209 {
3210 if (SUCCEED != DBdelete_template_elements(host->hostid, &host->del_templateids, &err))
3211 {
3212 *error = zbx_strdcatf(*error, "Cannot unlink template: %s.\n", err);
3213 zbx_free(err);
3214 }
3215 }
3216
3217 if (0 != host->lnk_templateids.values_num)
3218 {
3219 if (SUCCEED != DBcopy_template_elements(host->hostid, &host->lnk_templateids, &err))
3220 {
3221 *error = zbx_strdcatf(*error, "Cannot link template(s) %s.\n", err);
3222 zbx_free(err);
3223 }
3224 }
3225 }
3226
3227 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3228 }
3229
3230 /******************************************************************************
3231 * *
3232 * Function: lld_hosts_remove *
3233 * *
3234 * Purpose: updates host_discovery.lastcheck and host_discovery.ts_delete *
3235 * fields; removes lost resources *
3236 * *
3237 ******************************************************************************/
lld_hosts_remove(const zbx_vector_ptr_t * hosts,int lifetime,int lastcheck)3238 static void lld_hosts_remove(const zbx_vector_ptr_t *hosts, int lifetime, int lastcheck)
3239 {
3240 char *sql = NULL;
3241 size_t sql_alloc = 0, sql_offset = 0;
3242 const zbx_lld_host_t *host;
3243 zbx_vector_uint64_t del_hostids, lc_hostids, ts_hostids;
3244 int i;
3245
3246 if (0 == hosts->values_num)
3247 return;
3248
3249 zbx_vector_uint64_create(&del_hostids);
3250 zbx_vector_uint64_create(&lc_hostids);
3251 zbx_vector_uint64_create(&ts_hostids);
3252
3253 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3254
3255 for (i = 0; i < hosts->values_num; i++)
3256 {
3257 host = (zbx_lld_host_t *)hosts->values[i];
3258
3259 if (0 == host->hostid)
3260 continue;
3261
3262 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
3263 {
3264 int ts_delete = lld_end_of_life(host->lastcheck, lifetime);
3265
3266 if (lastcheck > ts_delete)
3267 {
3268 zbx_vector_uint64_append(&del_hostids, host->hostid);
3269 }
3270 else if (host->ts_delete != ts_delete)
3271 {
3272 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3273 "update host_discovery"
3274 " set ts_delete=%d"
3275 " where hostid=" ZBX_FS_UI64 ";\n",
3276 ts_delete, host->hostid);
3277 }
3278 }
3279 else
3280 {
3281 zbx_vector_uint64_append(&lc_hostids, host->hostid);
3282 if (0 != host->ts_delete)
3283 zbx_vector_uint64_append(&ts_hostids, host->hostid);
3284 }
3285 }
3286
3287 if (0 != lc_hostids.values_num)
3288 {
3289 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update host_discovery set lastcheck=%d where",
3290 lastcheck);
3291 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
3292 lc_hostids.values, lc_hostids.values_num);
3293 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3294 }
3295
3296 if (0 != ts_hostids.values_num)
3297 {
3298 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update host_discovery set ts_delete=0 where");
3299 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
3300 ts_hostids.values, ts_hostids.values_num);
3301 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3302 }
3303
3304 if (16 < sql_offset) /* in ORACLE always present begin..end; */
3305 {
3306 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3307
3308 DBbegin();
3309
3310 DBexecute("%s", sql);
3311
3312 DBcommit();
3313 }
3314
3315 zbx_free(sql);
3316
3317 if (0 != del_hostids.values_num)
3318 {
3319 zbx_vector_uint64_sort(&del_hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3320
3321 DBbegin();
3322
3323 DBdelete_hosts(&del_hostids);
3324
3325 DBcommit();
3326 }
3327
3328 zbx_vector_uint64_destroy(&ts_hostids);
3329 zbx_vector_uint64_destroy(&lc_hostids);
3330 zbx_vector_uint64_destroy(&del_hostids);
3331 }
3332
3333 /******************************************************************************
3334 * *
3335 * Function: lld_groups_remove *
3336 * *
3337 * Purpose: updates group_discovery.lastcheck and group_discovery.ts_delete *
3338 * fields; removes lost resources *
3339 * *
3340 ******************************************************************************/
lld_groups_remove(const zbx_vector_ptr_t * groups,int lifetime,int lastcheck)3341 static void lld_groups_remove(const zbx_vector_ptr_t *groups, int lifetime, int lastcheck)
3342 {
3343 char *sql = NULL;
3344 size_t sql_alloc = 0, sql_offset = 0;
3345 const zbx_lld_group_t *group;
3346 zbx_vector_uint64_t del_groupids, lc_groupids, ts_groupids;
3347 int i;
3348
3349 if (0 == groups->values_num)
3350 return;
3351
3352 zbx_vector_uint64_create(&del_groupids);
3353 zbx_vector_uint64_create(&lc_groupids);
3354 zbx_vector_uint64_create(&ts_groupids);
3355
3356 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3357
3358 for (i = 0; i < groups->values_num; i++)
3359 {
3360 group = (zbx_lld_group_t *)groups->values[i];
3361
3362 if (0 == group->groupid)
3363 continue;
3364
3365 if (0 == (group->flags & ZBX_FLAG_LLD_GROUP_DISCOVERED))
3366 {
3367 int ts_delete = lld_end_of_life(group->lastcheck, lifetime);
3368
3369 if (lastcheck > ts_delete)
3370 {
3371 zbx_vector_uint64_append(&del_groupids, group->groupid);
3372 }
3373 else if (group->ts_delete != ts_delete)
3374 {
3375 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3376 "update group_discovery"
3377 " set ts_delete=%d"
3378 " where groupid=" ZBX_FS_UI64 ";\n",
3379 ts_delete, group->groupid);
3380 }
3381 }
3382 else
3383 {
3384 zbx_vector_uint64_append(&lc_groupids, group->groupid);
3385 if (0 != group->ts_delete)
3386 zbx_vector_uint64_append(&ts_groupids, group->groupid);
3387 }
3388 }
3389
3390 if (0 != lc_groupids.values_num)
3391 {
3392 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update group_discovery set lastcheck=%d where",
3393 lastcheck);
3394 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
3395 lc_groupids.values, lc_groupids.values_num);
3396 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3397 }
3398
3399 if (0 != ts_groupids.values_num)
3400 {
3401 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update group_discovery set ts_delete=0 where");
3402 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid",
3403 ts_groupids.values, ts_groupids.values_num);
3404 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3405 }
3406
3407 if (16 < sql_offset) /* in ORACLE always present begin..end; */
3408 {
3409 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3410
3411 DBbegin();
3412
3413 DBexecute("%s", sql);
3414
3415 DBcommit();
3416 }
3417
3418 zbx_free(sql);
3419
3420 if (0 != del_groupids.values_num)
3421 {
3422 zbx_vector_uint64_sort(&del_groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3423
3424 DBbegin();
3425
3426 DBdelete_groups(&del_groupids);
3427
3428 DBcommit();
3429 }
3430
3431 zbx_vector_uint64_destroy(&ts_groupids);
3432 zbx_vector_uint64_destroy(&lc_groupids);
3433 zbx_vector_uint64_destroy(&del_groupids);
3434 }
3435
3436 /******************************************************************************
3437 * *
3438 * Function: lld_interfaces_get *
3439 * *
3440 * Purpose: retrieves either the list of interfaces from the lld rule's host *
3441 * or the list of custom interfaces defined for the host prototype *
3442 * *
3443 ******************************************************************************/
lld_interfaces_get(zbx_uint64_t id,zbx_vector_ptr_t * interfaces,unsigned char custom_interfaces)3444 static void lld_interfaces_get(zbx_uint64_t id, zbx_vector_ptr_t *interfaces, unsigned char custom_interfaces)
3445 {
3446 DB_RESULT result;
3447 DB_ROW row;
3448 zbx_lld_interface_t *interface;
3449
3450 if (ZBX_HOST_PROT_INTERFACES_INHERIT == custom_interfaces)
3451 {
3452 result = DBselect(
3453 "select hi.interfaceid,hi.type,hi.main,hi.useip,hi.ip,hi.dns,hi.port,s.version,s.bulk,"
3454 "s.community,s.securityname,s.securitylevel,s.authpassphrase,s.privpassphrase,"
3455 "s.authprotocol,s.privprotocol,s.contextname"
3456 " from interface hi"
3457 " inner join items i"
3458 " on hi.hostid=i.hostid "
3459 " left join interface_snmp s"
3460 " on hi.interfaceid=s.interfaceid"
3461 " where i.itemid=" ZBX_FS_UI64,
3462 id);
3463 }
3464 else
3465 {
3466 result = DBselect(
3467 "select hi.interfaceid,hi.type,hi.main,hi.useip,hi.ip,hi.dns,hi.port,s.version,s.bulk,"
3468 "s.community,s.securityname,s.securitylevel,s.authpassphrase,s.privpassphrase,"
3469 "s.authprotocol,s.privprotocol,s.contextname"
3470 " from interface hi"
3471 " left join interface_snmp s"
3472 " on hi.interfaceid=s.interfaceid"
3473 " where hi.hostid=" ZBX_FS_UI64,
3474 id);
3475 }
3476
3477 while (NULL != (row = DBfetch(result)))
3478 {
3479 interface = (zbx_lld_interface_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
3480
3481 ZBX_STR2UINT64(interface->interfaceid, row[0]);
3482 interface->type = (unsigned char)atoi(row[1]);
3483 interface->main = (unsigned char)atoi(row[2]);
3484 interface->useip = (unsigned char)atoi(row[3]);
3485 interface->ip = zbx_strdup(NULL, row[4]);
3486 interface->dns = zbx_strdup(NULL, row[5]);
3487 interface->port = zbx_strdup(NULL, row[6]);
3488
3489 if (INTERFACE_TYPE_SNMP == interface->type)
3490 {
3491 zbx_lld_interface_snmp_t *snmp;
3492
3493 snmp = (zbx_lld_interface_snmp_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_snmp_t));
3494 ZBX_STR2UCHAR(snmp->version, row[7]);
3495 ZBX_STR2UCHAR(snmp->bulk, row[8]);
3496 snmp->community = zbx_strdup(NULL, row[9]);
3497 snmp->securityname = zbx_strdup(NULL, row[10]);
3498 ZBX_STR2UCHAR(snmp->securitylevel, row[11]);
3499 snmp->authpassphrase = zbx_strdup(NULL, row[12]);
3500 snmp->privpassphrase = zbx_strdup(NULL, row[13]);
3501 ZBX_STR2UCHAR(snmp->authprotocol, row[14]);
3502 ZBX_STR2UCHAR(snmp->privprotocol, row[15]);
3503 snmp->contextname = zbx_strdup(NULL, row[16]);
3504 interface->data.snmp = snmp;
3505 interface->flags = ZBX_FLAG_LLD_INTERFACE_SNMP_DATA_EXISTS;
3506 }
3507 else
3508 {
3509 interface->data.snmp = NULL;
3510 interface->flags = 0x00;
3511 }
3512
3513 zbx_vector_ptr_append(interfaces, interface);
3514 }
3515 DBfree_result(result);
3516
3517 zbx_vector_ptr_sort(interfaces, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3518 }
3519
3520 /******************************************************************************
3521 * *
3522 * Function: lld_interface_make *
3523 * *
3524 ******************************************************************************/
lld_interface_make(zbx_vector_ptr_t * interfaces,zbx_uint64_t parent_interfaceid,zbx_uint64_t interfaceid,unsigned char type,unsigned char main,unsigned char useip,const char * ip,const char * dns,const char * port,unsigned char snmp_type,unsigned char bulk,const char * community,const char * securityname,unsigned char securitylevel,const char * authpassphrase,const char * privpassphrase,unsigned char authprotocol,unsigned char privprotocol,const char * contextname)3525 static void lld_interface_make(zbx_vector_ptr_t *interfaces, zbx_uint64_t parent_interfaceid,
3526 zbx_uint64_t interfaceid, unsigned char type, unsigned char main, unsigned char useip, const char *ip,
3527 const char *dns, const char *port, unsigned char snmp_type, unsigned char bulk, const char *community,
3528 const char *securityname, unsigned char securitylevel, const char *authpassphrase,
3529 const char *privpassphrase, unsigned char authprotocol, unsigned char privprotocol,
3530 const char *contextname)
3531 {
3532 zbx_lld_interface_t *interface = NULL;
3533 int i, interface_found = 0;
3534
3535 for (i = 0; i < interfaces->values_num; i++)
3536 {
3537 interface = (zbx_lld_interface_t *)interfaces->values[i];
3538
3539 if (0 != interface->interfaceid)
3540 continue;
3541
3542 if (interface->parent_interfaceid == parent_interfaceid)
3543 {
3544 interface_found = 1;
3545 break;
3546 }
3547 }
3548
3549 if (0 == interface_found)
3550 {
3551 /* interface should be deleted */
3552 interface = (zbx_lld_interface_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
3553
3554 interface->interfaceid = interfaceid;
3555 interface->parent_interfaceid = 0;
3556 interface->type = type;
3557 interface->main = main;
3558 interface->useip = 0;
3559 interface->ip = NULL;
3560 interface->dns = NULL;
3561 interface->port = NULL;
3562 interface->data.snmp = NULL;
3563 interface->flags = ZBX_FLAG_LLD_INTERFACE_REMOVE;
3564
3565 zbx_vector_ptr_append(interfaces, interface);
3566 }
3567 else
3568 {
3569 /* interface already has been added */
3570 if (interface->type != type)
3571 {
3572 interface->type_orig = type;
3573 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE;
3574
3575 if (INTERFACE_TYPE_SNMP == type)
3576 interface->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_REMOVE;
3577
3578 if (INTERFACE_TYPE_SNMP == interface->type)
3579 interface->data.snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_CREATE;
3580 }
3581 if (interface->main != main)
3582 {
3583 interface->main_orig = main;
3584 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
3585 }
3586 if (interface->useip != useip)
3587 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP;
3588 if (0 != strcmp(interface->ip, ip))
3589 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_IP;
3590 if (0 != strcmp(interface->dns, dns))
3591 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS;
3592 if (0 != strcmp(interface->port, port))
3593 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT;
3594
3595 if (INTERFACE_TYPE_SNMP == interface->type && interface->type == type)
3596 {
3597 zbx_lld_interface_snmp_t *snmp = interface->data.snmp;
3598
3599 if (snmp->version != snmp_type)
3600 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_TYPE;
3601 if (snmp->bulk != bulk)
3602 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_BULK;
3603 if (0 != strcmp(snmp->community, community))
3604 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_COMMUNITY;
3605 if (0 != strcmp(snmp->securityname, securityname))
3606 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECNAME;
3607 if (snmp->securitylevel != securitylevel)
3608 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECLEVEL;
3609 if (0 != strcmp(snmp->authpassphrase, authpassphrase))
3610 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPASS;
3611 if (0 != strcmp(snmp->privpassphrase, privpassphrase))
3612 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPASS;
3613 if (snmp->authprotocol != authprotocol)
3614 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPROTOCOL;
3615 if (snmp->privprotocol != privprotocol)
3616 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPROTOCOL;
3617 if (0 != strcmp(snmp->contextname, contextname))
3618 snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_CONTEXT;
3619 }
3620 }
3621
3622 interface->interfaceid = interfaceid;
3623 }
3624
3625 /******************************************************************************
3626 * *
3627 * Function: lld_interfaces_make *
3628 * *
3629 * Parameters: interfaces - [IN] sorted list of interfaces which *
3630 * should be present on the each *
3631 * discovered host *
3632 * hosts - [IN/OUT] sorted list of hosts *
3633 * lld_macros - [IN] list of LLD macros *
3634 * *
3635 ******************************************************************************/
lld_interfaces_make(const zbx_vector_ptr_t * interfaces,zbx_vector_ptr_t * hosts,const zbx_vector_ptr_t * lld_macros)3636 static void lld_interfaces_make(const zbx_vector_ptr_t *interfaces, zbx_vector_ptr_t *hosts,
3637 const zbx_vector_ptr_t *lld_macros)
3638 {
3639 DB_RESULT result;
3640 DB_ROW row;
3641 int i, j;
3642 zbx_vector_uint64_t hostids;
3643 zbx_uint64_t parent_interfaceid, hostid, interfaceid;
3644 zbx_lld_host_t *host;
3645 zbx_lld_interface_t *new_interface, *interface;
3646
3647 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3648
3649 zbx_vector_uint64_create(&hostids);
3650
3651 for (i = 0; i < hosts->values_num; i++)
3652 {
3653 host = (zbx_lld_host_t *)hosts->values[i];
3654
3655 if (0 == (host->flags & ZBX_FLAG_LLD_HOST_DISCOVERED))
3656 continue;
3657
3658 zbx_vector_ptr_reserve(&host->interfaces, interfaces->values_num);
3659
3660 for (j = 0; j < interfaces->values_num; j++)
3661 {
3662 interface = (zbx_lld_interface_t *)interfaces->values[j];
3663
3664 new_interface = (zbx_lld_interface_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_t));
3665
3666 new_interface->interfaceid = 0;
3667 new_interface->parent_interfaceid = interface->interfaceid;
3668 new_interface->type = interface->type;
3669 new_interface->main = interface->main;
3670 new_interface->useip = interface->useip;
3671 new_interface->ip = zbx_strdup(NULL, interface->ip);
3672 new_interface->dns = zbx_strdup(NULL, interface->dns);
3673 new_interface->port = zbx_strdup(NULL, interface->port);
3674
3675 substitute_lld_macros(&new_interface->ip, host->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
3676 substitute_lld_macros(&new_interface->dns, host->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
3677 substitute_lld_macros(&new_interface->port, host->jp_row, lld_macros, ZBX_MACRO_ANY, NULL, 0);
3678
3679 if (INTERFACE_TYPE_SNMP == interface->type)
3680 {
3681 zbx_lld_interface_snmp_t *snmp;
3682
3683 snmp = (zbx_lld_interface_snmp_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_snmp_t));
3684 snmp->version = interface->data.snmp->version;
3685 snmp->bulk = interface->data.snmp->bulk;
3686 snmp->community = zbx_strdup(NULL, interface->data.snmp->community);
3687 snmp->securityname = zbx_strdup(NULL, interface->data.snmp->securityname);
3688 snmp->securitylevel = interface->data.snmp->securitylevel;
3689 snmp->authpassphrase = zbx_strdup(NULL, interface->data.snmp->authpassphrase);
3690 snmp->privpassphrase = zbx_strdup(NULL, interface->data.snmp->privpassphrase);
3691 snmp->authprotocol = interface->data.snmp->authprotocol;
3692 snmp->privprotocol = interface->data.snmp->privprotocol;
3693 snmp->contextname = zbx_strdup(NULL, interface->data.snmp->contextname);
3694 snmp->flags = 0x00;
3695 new_interface->flags = ZBX_FLAG_LLD_INTERFACE_SNMP_DATA_EXISTS;
3696 new_interface->data.snmp = snmp;
3697
3698 substitute_lld_macros(&snmp->community, host->jp_row, lld_macros, ZBX_MACRO_ANY,
3699 NULL, 0);
3700 substitute_lld_macros(&snmp->securityname, host->jp_row, lld_macros, ZBX_MACRO_ANY,
3701 NULL, 0);
3702 substitute_lld_macros(&snmp->authpassphrase, host->jp_row, lld_macros, ZBX_MACRO_ANY,
3703 NULL, 0);
3704 substitute_lld_macros(&snmp->privpassphrase, host->jp_row, lld_macros, ZBX_MACRO_ANY,
3705 NULL, 0);
3706 substitute_lld_macros(&snmp->contextname, host->jp_row, lld_macros, ZBX_MACRO_ANY,
3707 NULL, 0);
3708 }
3709 else
3710 {
3711 new_interface->flags = 0x00;
3712 new_interface->data.snmp = NULL;
3713 }
3714
3715 zbx_vector_ptr_append(&host->interfaces, new_interface);
3716 }
3717
3718 if (0 != host->hostid)
3719 zbx_vector_uint64_append(&hostids, host->hostid);
3720 }
3721
3722 if (0 != hostids.values_num)
3723 {
3724 char *sql = NULL;
3725 size_t sql_alloc = 0, sql_offset = 0;
3726
3727 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3728 "select hi.hostid,id.parent_interfaceid,hi.interfaceid,hi.type,hi.main,hi.useip,hi.ip,"
3729 "hi.dns,hi.port,s.version,s.bulk,s.community,s.securityname,s.securitylevel,"
3730 "s.authpassphrase,s.privpassphrase,s.authprotocol,s.privprotocol,s.contextname"
3731 " from interface hi"
3732 " left join interface_discovery id"
3733 " on hi.interfaceid=id.interfaceid"
3734 " left join interface_snmp s"
3735 " on hi.interfaceid=s.interfaceid"
3736 " where");
3737 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hi.hostid", hostids.values, hostids.values_num);
3738
3739 result = DBselect("%s", sql);
3740
3741 zbx_free(sql);
3742
3743 while (NULL != (row = DBfetch(result)))
3744 {
3745 unsigned char interface_type;
3746
3747 ZBX_STR2UINT64(hostid, row[0]);
3748 ZBX_DBROW2UINT64(parent_interfaceid, row[1]);
3749 ZBX_DBROW2UINT64(interfaceid, row[2]);
3750
3751 if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3752 {
3753 THIS_SHOULD_NEVER_HAPPEN;
3754 continue;
3755 }
3756
3757 host = (zbx_lld_host_t *)hosts->values[i];
3758 ZBX_STR2UCHAR(interface_type, row[3]);
3759
3760 if (INTERFACE_TYPE_SNMP == interface_type)
3761 {
3762 lld_interface_make(&host->interfaces, parent_interfaceid, interfaceid,
3763 interface_type, (unsigned char)atoi(row[4]),
3764 (unsigned char)atoi(row[5]), row[6], row[7], row[8],
3765 (unsigned char)atoi(row[9]), (unsigned char)atoi(row[10]), row[11],
3766 row[12], (unsigned char)atoi(row[13]), row[14], row[15],
3767 (unsigned char)atoi(row[16]), (unsigned char)atoi(row[17]), row[18]);
3768 }
3769 else
3770 {
3771 lld_interface_make(&host->interfaces, parent_interfaceid, interfaceid,
3772 interface_type, (unsigned char)atoi(row[4]),
3773 (unsigned char)atoi(row[5]), row[6], row[7], row[8],
3774 0, 0, NULL, NULL, 0, NULL, NULL,0, 0, NULL);
3775 }
3776 }
3777 DBfree_result(result);
3778 }
3779
3780 zbx_vector_uint64_destroy(&hostids);
3781
3782 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3783 }
3784
3785 /******************************************************************************
3786 * *
3787 * Function: another_main_interface_exists *
3788 * *
3789 * Return value: SUCCEED if interface with same type exists in the list of *
3790 * interfaces; FAIL - otherwise *
3791 * *
3792 * Comments: interfaces with ZBX_FLAG_LLD_INTERFACE_REMOVE flag are ignored *
3793 * auxiliary function for lld_interfaces_validate() *
3794 * *
3795 ******************************************************************************/
another_main_interface_exists(const zbx_vector_ptr_t * interfaces,const zbx_lld_interface_t * interface)3796 static int another_main_interface_exists(const zbx_vector_ptr_t *interfaces, const zbx_lld_interface_t *interface)
3797 {
3798 const zbx_lld_interface_t *interface_b;
3799 int i;
3800
3801 for (i = 0; i < interfaces->values_num; i++)
3802 {
3803 interface_b = (zbx_lld_interface_t *)interfaces->values[i];
3804
3805 if (interface_b == interface)
3806 continue;
3807
3808 if (0 != (interface_b->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
3809 continue;
3810
3811 if (interface_b->type != interface->type)
3812 continue;
3813
3814 if (1 == interface_b->main)
3815 return SUCCEED;
3816 }
3817
3818 return FAIL;
3819 }
3820
3821 /******************************************************************************
3822 * *
3823 * Function: lld_interfaces_validate *
3824 * *
3825 * Parameters: hosts - [IN/OUT] list of hosts *
3826 * *
3827 ******************************************************************************/
lld_interfaces_validate(zbx_vector_ptr_t * hosts,char ** error)3828 static void lld_interfaces_validate(zbx_vector_ptr_t *hosts, char **error)
3829 {
3830 DB_RESULT result;
3831 DB_ROW row;
3832 int i, j;
3833 zbx_vector_uint64_t interfaceids;
3834 zbx_uint64_t interfaceid;
3835 zbx_lld_host_t *host;
3836 zbx_lld_interface_t *interface;
3837 unsigned char type;
3838 char *sql = NULL;
3839 size_t sql_alloc = 0, sql_offset = 0;
3840
3841 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
3842
3843 /* validate changed types */
3844
3845 zbx_vector_uint64_create(&interfaceids);
3846
3847 for (i = 0; i < hosts->values_num; i++)
3848 {
3849 host = (zbx_lld_host_t *)hosts->values[i];
3850
3851 for (j = 0; j < host->interfaces.values_num; j++)
3852 {
3853 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
3854
3855 if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
3856 continue;
3857
3858 zbx_vector_uint64_append(&interfaceids, interface->interfaceid);
3859 }
3860 }
3861
3862 if (0 != interfaceids.values_num)
3863 {
3864 zbx_vector_uint64_sort(&interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3865
3866 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select interfaceid,type from items where");
3867 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "interfaceid",
3868 interfaceids.values, interfaceids.values_num);
3869 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " group by interfaceid,type");
3870
3871 result = DBselect("%s", sql);
3872
3873 while (NULL != (row = DBfetch(result)))
3874 {
3875 type = get_interface_type_by_item_type((unsigned char)atoi(row[1]));
3876
3877 if (type != INTERFACE_TYPE_ANY && type != INTERFACE_TYPE_UNKNOWN)
3878 {
3879 ZBX_STR2UINT64(interfaceid, row[0]);
3880
3881 for (i = 0; i < hosts->values_num; i++)
3882 {
3883 host = (zbx_lld_host_t *)hosts->values[i];
3884
3885 for (j = 0; j < host->interfaces.values_num; j++)
3886 {
3887 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
3888
3889 if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE))
3890 continue;
3891
3892 if (interface->interfaceid != interfaceid)
3893 continue;
3894
3895 *error = zbx_strdcatf(*error,
3896 "Cannot update \"%s\" interface on host \"%s\":"
3897 " the interface is used by items.\n",
3898 zbx_interface_type_string(interface->type_orig),
3899 host->host);
3900
3901 /* return an original interface type and drop the corresponding flag */
3902 interface->type = interface->type_orig;
3903 interface->flags &= ~ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE;
3904 }
3905 }
3906 }
3907 }
3908 DBfree_result(result);
3909 }
3910
3911 /* validate interfaces which should be deleted */
3912
3913 zbx_vector_uint64_clear(&interfaceids);
3914
3915 for (i = 0; i < hosts->values_num; i++)
3916 {
3917 host = (zbx_lld_host_t *)hosts->values[i];
3918
3919 for (j = 0; j < host->interfaces.values_num; j++)
3920 {
3921 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
3922
3923 if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
3924 continue;
3925
3926 zbx_vector_uint64_append(&interfaceids, interface->interfaceid);
3927 }
3928 }
3929
3930 if (0 != interfaceids.values_num)
3931 {
3932 zbx_vector_uint64_sort(&interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3933
3934 sql_offset = 0;
3935 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select interfaceid from items where");
3936 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "interfaceid",
3937 interfaceids.values, interfaceids.values_num);
3938 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " group by interfaceid");
3939
3940 result = DBselect("%s", sql);
3941
3942 while (NULL != (row = DBfetch(result)))
3943 {
3944 ZBX_STR2UINT64(interfaceid, row[0]);
3945
3946 for (i = 0; i < hosts->values_num; i++)
3947 {
3948 host = (zbx_lld_host_t *)hosts->values[i];
3949
3950 for (j = 0; j < host->interfaces.values_num; j++)
3951 {
3952 interface = (zbx_lld_interface_t *)host->interfaces.values[j];
3953
3954 if (0 == (interface->flags & ZBX_FLAG_LLD_INTERFACE_REMOVE))
3955 continue;
3956
3957 if (interface->interfaceid != interfaceid)
3958 continue;
3959
3960 *error = zbx_strdcatf(*error, "Cannot delete \"%s\" interface on host \"%s\":"
3961 " the interface is used by items.\n",
3962 zbx_interface_type_string(interface->type), host->host);
3963
3964 /* drop the corresponding flag */
3965 interface->flags &= ~ZBX_FLAG_LLD_INTERFACE_REMOVE;
3966
3967 if (SUCCEED == another_main_interface_exists(&host->interfaces, interface))
3968 {
3969 if (1 == interface->main)
3970 {
3971 /* drop main flag */
3972 interface->main_orig = interface->main;
3973 interface->main = 0;
3974 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
3975 }
3976 }
3977 else if (1 != interface->main)
3978 {
3979 /* set main flag */
3980 interface->main_orig = interface->main;
3981 interface->main = 1;
3982 interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN;
3983 }
3984 }
3985 }
3986 }
3987 DBfree_result(result);
3988 }
3989
3990 zbx_vector_uint64_destroy(&interfaceids);
3991
3992 zbx_free(sql);
3993
3994 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
3995 }
3996
3997 /******************************************************************************
3998 * *
3999 * Function: lld_update_hosts *
4000 * *
4001 * Purpose: add or update low-level discovered hosts *
4002 * *
4003 ******************************************************************************/
lld_update_hosts(zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * lld_rows,const zbx_vector_ptr_t * lld_macro_paths,char ** error,int lifetime,int lastcheck)4004 void lld_update_hosts(zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *lld_rows,
4005 const zbx_vector_ptr_t *lld_macro_paths, char **error, int lifetime, int lastcheck)
4006 {
4007 DB_RESULT result;
4008 DB_ROW row;
4009 zbx_vector_ptr_t hosts, group_prototypes, groups, interfaces, masterhostmacros, hostmacros;
4010 zbx_vector_db_tag_ptr_t tags;
4011 zbx_vector_uint64_t groupids; /* list of host groups which should be added */
4012 zbx_vector_uint64_t del_hostgroupids; /* list of host groups which should be deleted */
4013 zbx_uint64_t proxy_hostid;
4014 char *ipmi_username = NULL, *ipmi_password, *tls_issuer, *tls_subject, *tls_psk_identity,
4015 *tls_psk;
4016 char ipmi_authtype, inventory_mode_proto;
4017 unsigned char ipmi_privilege, tls_connect, tls_accept;
4018
4019 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
4020
4021 result = DBselect(
4022 "select h.proxy_hostid,h.ipmi_authtype,h.ipmi_privilege,h.ipmi_username,h.ipmi_password,"
4023 "h.tls_connect,h.tls_accept,h.tls_issuer,h.tls_subject,h.tls_psk_identity,h.tls_psk"
4024 " from hosts h,items i"
4025 " where h.hostid=i.hostid"
4026 " and i.itemid=" ZBX_FS_UI64,
4027 lld_ruleid);
4028
4029 if (NULL != (row = DBfetch(result)))
4030 {
4031 ZBX_DBROW2UINT64(proxy_hostid, row[0]);
4032 ipmi_authtype = (char)atoi(row[1]);
4033 ZBX_STR2UCHAR(ipmi_privilege, row[2]);
4034 ipmi_username = zbx_strdup(NULL, row[3]);
4035 ipmi_password = zbx_strdup(NULL, row[4]);
4036
4037 ZBX_STR2UCHAR(tls_connect, row[5]);
4038 ZBX_STR2UCHAR(tls_accept, row[6]);
4039 tls_issuer = zbx_strdup(NULL, row[7]);
4040 tls_subject = zbx_strdup(NULL, row[8]);
4041 tls_psk_identity = zbx_strdup(NULL, row[9]);
4042 tls_psk = zbx_strdup(NULL, row[10]);
4043 }
4044 DBfree_result(result);
4045
4046 if (NULL == row)
4047 {
4048 *error = zbx_strdcatf(*error, "Cannot process host prototypes: a parent host not found.\n");
4049 return;
4050 }
4051
4052 zbx_vector_ptr_create(&hosts);
4053 zbx_vector_uint64_create(&groupids);
4054 zbx_vector_ptr_create(&group_prototypes);
4055 zbx_vector_ptr_create(&groups);
4056 zbx_vector_uint64_create(&del_hostgroupids);
4057 zbx_vector_ptr_create(&interfaces);
4058 zbx_vector_ptr_create(&masterhostmacros);
4059 zbx_vector_ptr_create(&hostmacros);
4060 zbx_vector_db_tag_ptr_create(&tags);
4061
4062 lld_interfaces_get(lld_ruleid, &interfaces, 0);
4063 lld_masterhostmacros_get(lld_ruleid, &masterhostmacros);
4064
4065 result = DBselect(
4066 "select h.hostid,h.host,h.name,h.status,h.discover,hi.inventory_mode,h.custom_interfaces"
4067 " from hosts h,host_discovery hd"
4068 " left join host_inventory hi"
4069 " on hd.hostid=hi.hostid"
4070 " where h.hostid=hd.hostid"
4071 " and hd.parent_itemid=" ZBX_FS_UI64,
4072 lld_ruleid);
4073
4074 while (NULL != (row = DBfetch(result)))
4075 {
4076 zbx_uint64_t parent_hostid;
4077 const char *host_proto, *name_proto;
4078 zbx_lld_host_t *host;
4079 unsigned char status, discover, use_custom_interfaces;
4080 int i;
4081 zbx_vector_ptr_t interfaces_custom;
4082
4083 ZBX_STR2UINT64(parent_hostid, row[0]);
4084 host_proto = row[1];
4085 name_proto = row[2];
4086 ZBX_STR2UCHAR(status, row[3]);
4087 ZBX_STR2UCHAR(discover, row[4]);
4088 ZBX_STR2UCHAR(use_custom_interfaces, row[6]);
4089
4090 if (SUCCEED == DBis_null(row[5]))
4091 inventory_mode_proto = HOST_INVENTORY_DISABLED;
4092 else
4093 inventory_mode_proto = (char)atoi(row[5]);
4094
4095 lld_hosts_get(parent_hostid, &hosts, proxy_hostid, ipmi_authtype, ipmi_privilege, ipmi_username,
4096 ipmi_password, tls_connect, tls_accept, tls_issuer, tls_subject,
4097 tls_psk_identity, tls_psk);
4098
4099 if (0 != hosts.values_num)
4100 lld_hosts_get_tags(&hosts);
4101 lld_proto_tags_get(parent_hostid, &tags);
4102
4103 lld_simple_groups_get(parent_hostid, &groupids);
4104 lld_group_prototypes_get(parent_hostid, &group_prototypes);
4105 lld_groups_get(parent_hostid, &groups);
4106
4107 lld_hostmacros_get(parent_hostid, &masterhostmacros, &hostmacros);
4108
4109 for (i = 0; i < lld_rows->values_num; i++)
4110 {
4111 const zbx_lld_row_t *lld_row = (zbx_lld_row_t *)lld_rows->values[i];
4112
4113 if (NULL == (host = lld_host_make(&hosts, host_proto, name_proto, inventory_mode_proto,
4114 status, discover, &tags, lld_row, lld_macro_paths, error, use_custom_interfaces)))
4115 {
4116 continue;
4117 }
4118
4119 lld_groups_make(host, &groups, &group_prototypes, &lld_row->jp_row, lld_macro_paths);
4120 }
4121
4122 zbx_vector_ptr_sort(&hosts, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4123
4124 lld_groups_validate(&groups, error);
4125 lld_hosts_validate(&hosts, error);
4126
4127 if (ZBX_HOST_PROT_INTERFACES_CUSTOM == use_custom_interfaces)
4128 {
4129 zbx_vector_ptr_create(&interfaces_custom);
4130 lld_interfaces_get(parent_hostid, &interfaces_custom, 1);
4131 lld_interfaces_make(&interfaces_custom, &hosts, lld_macro_paths);
4132 }
4133 else
4134 lld_interfaces_make(&interfaces, &hosts, lld_macro_paths);
4135
4136 lld_interfaces_validate(&hosts, error);
4137
4138 lld_hostgroups_make(&groupids, &hosts, &groups, &del_hostgroupids);
4139 lld_templates_make(parent_hostid, &hosts);
4140
4141 lld_hostmacros_make(&hostmacros, &hosts, lld_macro_paths);
4142
4143 lld_groups_save(&groups, &group_prototypes);
4144 lld_hosts_save(parent_hostid, &hosts, host_proto, proxy_hostid, ipmi_authtype, ipmi_privilege,
4145 ipmi_username, ipmi_password, tls_connect, tls_accept,
4146 tls_issuer, tls_subject, tls_psk_identity, tls_psk, &del_hostgroupids);
4147
4148 /* linking of the templates */
4149 lld_templates_link(&hosts, error);
4150
4151 lld_hosts_remove(&hosts, lifetime, lastcheck);
4152 lld_groups_remove(&groups, lifetime, lastcheck);
4153
4154 zbx_vector_db_tag_ptr_clear_ext(&tags, zbx_db_tag_free);
4155 zbx_vector_ptr_clear_ext(&hostmacros, (zbx_clean_func_t)lld_hostmacro_free);
4156 zbx_vector_ptr_clear_ext(&groups, (zbx_clean_func_t)lld_group_free);
4157 zbx_vector_ptr_clear_ext(&group_prototypes, (zbx_clean_func_t)lld_group_prototype_free);
4158 zbx_vector_ptr_clear_ext(&hosts, (zbx_clean_func_t)lld_host_free);
4159
4160 zbx_vector_uint64_clear(&groupids);
4161 zbx_vector_uint64_clear(&del_hostgroupids);
4162
4163 if (ZBX_HOST_PROT_INTERFACES_CUSTOM == use_custom_interfaces)
4164 {
4165 zbx_vector_ptr_clear_ext(&interfaces_custom, (zbx_clean_func_t)lld_interface_free);
4166 zbx_vector_ptr_destroy(&interfaces_custom);
4167 }
4168 }
4169 DBfree_result(result);
4170
4171 zbx_vector_ptr_clear_ext(&masterhostmacros, (zbx_clean_func_t)lld_hostmacro_free);
4172 zbx_vector_ptr_clear_ext(&interfaces, (zbx_clean_func_t)lld_interface_free);
4173
4174 zbx_vector_db_tag_ptr_clear_ext(&tags, zbx_db_tag_free);
4175 zbx_vector_db_tag_ptr_destroy(&tags);
4176 zbx_vector_ptr_destroy(&hostmacros);
4177 zbx_vector_ptr_destroy(&masterhostmacros);
4178 zbx_vector_ptr_destroy(&interfaces);
4179 zbx_vector_uint64_destroy(&del_hostgroupids);
4180 zbx_vector_ptr_destroy(&groups);
4181 zbx_vector_ptr_destroy(&group_prototypes);
4182 zbx_vector_uint64_destroy(&groupids);
4183 zbx_vector_ptr_destroy(&hosts);
4184
4185 zbx_free(tls_psk);
4186 zbx_free(tls_psk_identity);
4187 zbx_free(tls_subject);
4188 zbx_free(tls_issuer);
4189 zbx_free(ipmi_password);
4190 zbx_free(ipmi_username);
4191
4192 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
4193 }
4194