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