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