1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "common.h"
21 #include "comms.h"
22 #include "db.h"
23 #include "log.h"
24 #include "dbcache.h"
25 
26 #include "operations.h"
27 #include "zbxserver.h"
28 
29 typedef enum
30 {
31 	ZBX_DISCOVERY_UNSPEC = 0,
32 	ZBX_DISCOVERY_DNS,
33 	ZBX_DISCOVERY_IP,
34 	ZBX_DISCOVERY_VALUE
35 }
36 zbx_dcheck_source_t;
37 
38 /******************************************************************************
39  *                                                                            *
40  * Function: select_discovered_host                                           *
41  *                                                                            *
42  * Purpose: select hostid of discovered host                                  *
43  *                                                                            *
44  * Parameters: dhostid - discovered host id                                   *
45  *                                                                            *
46  * Return value: hostid - existing hostid, 0 - if not found                   *
47  *                                                                            *
48  * Author: Alexei Vladishev                                                   *
49  *                                                                            *
50  ******************************************************************************/
select_discovered_host(const DB_EVENT * event)51 static zbx_uint64_t	select_discovered_host(const DB_EVENT *event)
52 {
53 	DB_RESULT	result;
54 	DB_ROW		row;
55 	zbx_uint64_t	hostid = 0, proxy_hostid;
56 	char		*sql = NULL, *ip_esc;
57 
58 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() eventid:" ZBX_FS_UI64, __func__, event->eventid);
59 
60 	switch (event->object)
61 	{
62 		case EVENT_OBJECT_DHOST:
63 		case EVENT_OBJECT_DSERVICE:
64 			result = DBselect(
65 					"select dr.proxy_hostid,ds.ip"
66 					" from drules dr,dchecks dc,dservices ds"
67 					" where dc.druleid=dr.druleid"
68 						" and ds.dcheckid=dc.dcheckid"
69 						" and ds.%s=" ZBX_FS_UI64,
70 					EVENT_OBJECT_DSERVICE == event->object ? "dserviceid" : "dhostid",
71 					event->objectid);
72 
73 			if (NULL == (row = DBfetch(result)))
74 			{
75 				DBfree_result(result);
76 				goto exit;
77 			}
78 
79 			ZBX_DBROW2UINT64(proxy_hostid, row[0]);
80 			ip_esc = DBdyn_escape_string(row[1]);
81 			DBfree_result(result);
82 
83 			sql = zbx_dsprintf(sql,
84 					"select h.hostid"
85 					" from hosts h,interface i"
86 					" where h.hostid=i.hostid"
87 						" and i.ip='%s'"
88 						" and i.useip=1"
89 						" and h.status in (%d,%d)"
90 						" and h.proxy_hostid%s"
91 					" order by i.hostid",
92 					ip_esc,
93 					HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
94 					DBsql_id_cmp(proxy_hostid));
95 
96 			zbx_free(ip_esc);
97 			break;
98 		case EVENT_OBJECT_ZABBIX_ACTIVE:
99 			sql = zbx_dsprintf(sql,
100 					"select h.hostid"
101 					" from hosts h,autoreg_host a"
102 					" where h.host=a.host"
103 						" and a.autoreg_hostid=" ZBX_FS_UI64
104 						" and h.status in (%d,%d)",
105 					event->objectid,
106 					HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED);
107 			break;
108 		default:
109 			goto exit;
110 	}
111 
112 	result = DBselectN(sql, 1);
113 
114 	zbx_free(sql);
115 
116 	if (NULL != (row = DBfetch(result)))
117 		ZBX_STR2UINT64(hostid, row[0]);
118 	DBfree_result(result);
119 exit:
120 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():" ZBX_FS_UI64, __func__, hostid);
121 
122 	return hostid;
123 }
124 
125 /******************************************************************************
126  *                                                                            *
127  * Function: add_discovered_host_groups                                       *
128  *                                                                            *
129  * Purpose: add group to host if not added already                            *
130  *                                                                            *
131  * Author: Alexander Vladishev                                                *
132  *                                                                            *
133  ******************************************************************************/
add_discovered_host_groups(zbx_uint64_t hostid,zbx_vector_uint64_t * groupids)134 static void	add_discovered_host_groups(zbx_uint64_t hostid, zbx_vector_uint64_t *groupids)
135 {
136 	DB_RESULT	result;
137 	DB_ROW		row;
138 	zbx_uint64_t	groupid;
139 	char		*sql = NULL;
140 	size_t		sql_alloc = 256, sql_offset = 0;
141 	int		i;
142 
143 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
144 
145 	sql = (char *)zbx_malloc(sql, sql_alloc);
146 
147 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
148 			"select groupid"
149 			" from hosts_groups"
150 			" where hostid=" ZBX_FS_UI64
151 				" and",
152 			hostid);
153 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
154 
155 	result = DBselect("%s", sql);
156 
157 	zbx_free(sql);
158 
159 	while (NULL != (row = DBfetch(result)))
160 	{
161 		ZBX_STR2UINT64(groupid, row[0]);
162 
163 		if (FAIL == (i = zbx_vector_uint64_search(groupids, groupid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
164 		{
165 			THIS_SHOULD_NEVER_HAPPEN;
166 			continue;
167 		}
168 
169 		zbx_vector_uint64_remove_noorder(groupids, i);
170 	}
171 	DBfree_result(result);
172 
173 	if (0 != groupids->values_num)
174 	{
175 		zbx_uint64_t	hostgroupid;
176 		zbx_db_insert_t	db_insert;
177 
178 		hostgroupid = DBget_maxid_num("hosts_groups", groupids->values_num);
179 
180 		zbx_db_insert_prepare(&db_insert, "hosts_groups", "hostgroupid", "hostid", "groupid", NULL);
181 
182 		zbx_vector_uint64_sort(groupids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
183 
184 		for (i = 0; i < groupids->values_num; i++)
185 		{
186 			zbx_db_insert_add_values(&db_insert, hostgroupid++, hostid, groupids->values[i]);
187 		}
188 
189 		zbx_db_insert_execute(&db_insert);
190 		zbx_db_insert_clean(&db_insert);
191 	}
192 
193 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
194 }
195 
196 /******************************************************************************
197  *                                                                            *
198  * Function: add_discovered_host                                              *
199  *                                                                            *
200  * Purpose: add discovered host if it was not added already                   *
201  *                                                                            *
202  * Parameters:                                                                *
203  *                                                                            *
204  * Return value: hostid - new/existing hostid                                 *
205  *                                                                            *
206  * Author: Alexei Vladishev                                                   *
207  *                                                                            *
208  ******************************************************************************/
add_discovered_host(const DB_EVENT * event)209 static zbx_uint64_t	add_discovered_host(const DB_EVENT *event)
210 {
211 	DB_RESULT		result;
212 	DB_RESULT		result2;
213 	DB_ROW			row;
214 	DB_ROW			row2;
215 	zbx_uint64_t		dhostid, hostid = 0, proxy_hostid, druleid;
216 	char			*host, *host_esc, *host_unique, *host_visible, *host_visible_unique;
217 	unsigned short		port;
218 	zbx_vector_uint64_t	groupids;
219 	unsigned char		svc_type, interface_type;
220 	zbx_config_t		cfg;
221 	zbx_db_insert_t		db_insert;
222 
223 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() eventid:" ZBX_FS_UI64, __func__, event->eventid);
224 
225 	zbx_vector_uint64_create(&groupids);
226 
227 	zbx_config_get(&cfg, ZBX_CONFIG_FLAGS_DISCOVERY_GROUPID | ZBX_CONFIG_FLAGS_DEFAULT_INVENTORY_MODE);
228 
229 	if (ZBX_DISCOVERY_GROUPID_UNDEFINED == cfg.discovery_groupid)
230 	{
231 		zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host: group for discovered hosts is not defined");
232 		goto clean;
233 	}
234 
235 	zbx_vector_uint64_append(&groupids, cfg.discovery_groupid);
236 
237 	if (EVENT_OBJECT_DHOST == event->object || EVENT_OBJECT_DSERVICE == event->object)
238 	{
239 		if (EVENT_OBJECT_DHOST == event->object)
240 		{
241 			result = DBselect(
242 					"select ds.dhostid,dr.proxy_hostid,ds.ip,ds.dns,ds.port,dc.type,"
243 						"dc.host_source,dc.name_source,dr.druleid,"
244 						"dc.snmp_community,dc.snmpv3_securityname,dc.snmpv3_securitylevel,"
245 						"dc.snmpv3_authpassphrase,dc.snmpv3_privpassphrase,"
246 						"dc.snmpv3_authprotocol,dc.snmpv3_privprotocol,dc.snmpv3_contextname"
247 					" from drules dr,dchecks dc,dservices ds"
248 					" where dc.druleid=dr.druleid"
249 						" and ds.dcheckid=dc.dcheckid"
250 						" and ds.dhostid=" ZBX_FS_UI64
251 					" order by ds.dserviceid",
252 					event->objectid);
253 		}
254 		else
255 		{
256 			result = DBselect(
257 					"select ds.dhostid,dr.proxy_hostid,ds.ip,ds.dns,ds.port,dc.type,"
258 						"dc.host_source,dc.name_source,dr.druleid,"
259 						"dc.snmp_community,dc.snmpv3_securityname,dc.snmpv3_securitylevel,"
260 						"dc.snmpv3_authpassphrase,dc.snmpv3_privpassphrase,"
261 						"dc.snmpv3_authprotocol,dc.snmpv3_privprotocol,dc.snmpv3_contextname"
262 					" from drules dr,dchecks dc,dservices ds,dservices ds1"
263 					" where dc.druleid=dr.druleid"
264 						" and ds.dcheckid=dc.dcheckid"
265 						" and ds1.dhostid=ds.dhostid"
266 						" and ds1.dserviceid=" ZBX_FS_UI64
267 					" order by ds.dserviceid",
268 					event->objectid);
269 		}
270 
271 		while (NULL != (row = DBfetch(result)))
272 		{
273 			zbx_uint64_t	interfaceid;
274 
275 			ZBX_STR2UINT64(dhostid, row[0]);
276 			ZBX_STR2UINT64(druleid, row[8]);
277 			ZBX_DBROW2UINT64(proxy_hostid, row[1]);
278 			svc_type = (unsigned char)atoi(row[5]);
279 
280 			switch (svc_type)
281 			{
282 				case SVC_AGENT:
283 					port = (unsigned short)atoi(row[4]);
284 					interface_type = INTERFACE_TYPE_AGENT;
285 					break;
286 				case SVC_SNMPv1:
287 				case SVC_SNMPv2c:
288 				case SVC_SNMPv3:
289 					port = (unsigned short)atoi(row[4]);
290 					interface_type = INTERFACE_TYPE_SNMP;
291 					break;
292 				default:
293 					port = ZBX_DEFAULT_AGENT_PORT;
294 					interface_type = INTERFACE_TYPE_AGENT;
295 			}
296 
297 			if (0 == hostid)
298 			{
299 				result2 = DBselect(
300 						"select distinct h.hostid"
301 						" from hosts h,interface i,dservices ds"
302 						" where h.hostid=i.hostid"
303 							" and i.ip=ds.ip"
304 							" and h.status in (%d,%d)"
305 							" and h.proxy_hostid%s"
306 							" and ds.dhostid=" ZBX_FS_UI64
307 						" order by h.hostid",
308 						HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED,
309 						DBsql_id_cmp(proxy_hostid), dhostid);
310 
311 				if (NULL != (row2 = DBfetch(result2)))
312 					ZBX_STR2UINT64(hostid, row2[0]);
313 
314 				DBfree_result(result2);
315 			}
316 
317 			if (0 == hostid)
318 			{
319 				DB_RESULT		result3;
320 				DB_ROW			row3;
321 				zbx_dcheck_source_t	host_source, name_source;
322 				char			*sql = NULL;
323 				size_t			sql_alloc, sql_offset;
324 
325 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
326 						"select ds.value"
327 						" from dchecks dc"
328 							" left join dservices ds"
329 								" on ds.dcheckid=dc.dcheckid"
330 									" and ds.dhostid=" ZBX_FS_UI64
331 						" where dc.druleid=" ZBX_FS_UI64
332 							" and dc.host_source=%d"
333 						" order by ds.dserviceid",
334 							dhostid, druleid, ZBX_DISCOVERY_VALUE);
335 
336 				result3 = DBselectN(sql, 1);
337 
338 				if (NULL != (row3 = DBfetch(result3)))
339 				{
340 					if (SUCCEED == zbx_db_is_null(row3[0]) || '\0' == *row3[0])
341 					{
342 						zabbix_log(LOG_LEVEL_WARNING, "cannot retrieve service value for"
343 								" host name on \"%s\"", row[2]);
344 						host_source = ZBX_DISCOVERY_DNS;
345 					}
346 					else
347 						host_source = ZBX_DISCOVERY_VALUE;
348 				}
349 				else
350 				{
351 					if (ZBX_DISCOVERY_VALUE == (host_source = atoi(row[6])))
352 					{
353 						zabbix_log(LOG_LEVEL_WARNING, "cannot retrieve service value for"
354 								" host name on \"%s\"", row[2]);
355 						host_source = ZBX_DISCOVERY_DNS;
356 					}
357 				}
358 
359 				if (ZBX_DISCOVERY_VALUE == host_source)
360 					host = zbx_strdup(NULL, row3[0]);
361 				else if (ZBX_DISCOVERY_IP == host_source || '\0' == *row[3])
362 					host = zbx_strdup(NULL, row[2]);
363 				else
364 					host = zbx_strdup(NULL, row[3]);
365 
366 				DBfree_result(result3);
367 
368 				/* for host uniqueness purposes */
369 				make_hostname(host);	/* replace not-allowed symbols */
370 				host_unique = DBget_unique_hostname_by_sample(host, "host");
371 				zbx_free(host);
372 
373 				sql_offset = 0;
374 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
375 						"select ds.value"
376 						" from dchecks dc"
377 							" left join dservices ds"
378 								" on ds.dcheckid=dc.dcheckid"
379 									" and ds.dhostid=" ZBX_FS_UI64
380 						" where dc.druleid=" ZBX_FS_UI64
381 							" and dc.host_source in (%d,%d,%d,%d)"
382 							" and dc.name_source=%d"
383 						" order by ds.dserviceid",
384 							dhostid, druleid, ZBX_DISCOVERY_UNSPEC, ZBX_DISCOVERY_DNS,
385 							ZBX_DISCOVERY_IP, ZBX_DISCOVERY_VALUE, ZBX_DISCOVERY_VALUE);
386 
387 				result3 = DBselectN(sql, 1);
388 
389 				if (NULL != (row3 = DBfetch(result3)))
390 				{
391 					if (SUCCEED == zbx_db_is_null(row3[0]) || '\0' == *row3[0])
392 					{
393 						zabbix_log(LOG_LEVEL_WARNING, "cannot retrieve service value for"
394 								" host visible name on \"%s\"", row[2]);
395 						name_source = ZBX_DISCOVERY_UNSPEC;
396 					}
397 					else
398 						name_source = ZBX_DISCOVERY_VALUE;
399 				}
400 				else
401 				{
402 					if (ZBX_DISCOVERY_VALUE == (name_source = atoi(row[7])))
403 					{
404 						zabbix_log(LOG_LEVEL_WARNING, "cannot retrieve service value for"
405 								" host visible name on \"%s\"", row[2]);
406 						name_source = ZBX_DISCOVERY_UNSPEC;
407 					}
408 				}
409 
410 				if (ZBX_DISCOVERY_VALUE == name_source)
411 					host_visible = zbx_strdup(NULL, row3[0]);
412 				else if (ZBX_DISCOVERY_IP == name_source ||
413 						(ZBX_DISCOVERY_DNS == name_source && '\0' == *row[3]))
414 					host_visible = zbx_strdup(NULL, row[2]);
415 				else if (ZBX_DISCOVERY_DNS == name_source)
416 					host_visible = zbx_strdup(NULL, row[3]);
417 				else
418 					host_visible = zbx_strdup(NULL, host_unique);
419 
420 				DBfree_result(result3);
421 				zbx_free(sql);
422 
423 				make_hostname(host_visible);	/* replace not-allowed symbols */
424 				host_visible_unique = DBget_unique_hostname_by_sample(host_visible, "name");
425 				zbx_free(host_visible);
426 
427 				hostid = DBget_maxid("hosts");
428 
429 				zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "proxy_hostid", "host", "name",
430 						NULL);
431 				zbx_db_insert_add_values(&db_insert, hostid, proxy_hostid, host_unique,
432 						host_visible_unique);
433 				zbx_db_insert_execute(&db_insert);
434 				zbx_db_insert_clean(&db_insert);
435 
436 				if (HOST_INVENTORY_DISABLED != cfg.default_inventory_mode)
437 					DBadd_host_inventory(hostid, cfg.default_inventory_mode);
438 
439 				interfaceid = DBadd_interface(hostid, interface_type, 1, row[2], row[3], port,
440 						ZBX_CONN_DEFAULT);
441 
442 				zbx_free(host_unique);
443 				zbx_free(host_visible_unique);
444 
445 				add_discovered_host_groups(hostid, &groupids);
446 			}
447 			else
448 				interfaceid = DBadd_interface(hostid, interface_type, 1, row[2], row[3], port,
449 						ZBX_CONN_DEFAULT);
450 
451 			if (INTERFACE_TYPE_SNMP == interface_type)
452 			{
453 				unsigned char securitylevel, authprotocol, privprotocol, version = ZBX_IF_SNMP_VERSION_2;
454 
455 				ZBX_STR2UCHAR(securitylevel, row[11]);
456 				ZBX_STR2UCHAR(authprotocol, row[14]);
457 				ZBX_STR2UCHAR(privprotocol, row[15]);
458 
459 				if (SVC_SNMPv1 == svc_type)
460 					version = ZBX_IF_SNMP_VERSION_1;
461 				else if (SVC_SNMPv3 == svc_type)
462 					version = ZBX_IF_SNMP_VERSION_3;
463 
464 				DBadd_interface_snmp(interfaceid, version, SNMP_BULK_ENABLED, row[9], row[10],
465 						securitylevel, row[12], row[13], authprotocol, privprotocol, row[16]);
466 			}
467 		}
468 		DBfree_result(result);
469 	}
470 	else if (EVENT_OBJECT_ZABBIX_ACTIVE == event->object)
471 	{
472 		result = DBselect(
473 				"select proxy_hostid,host,listen_ip,listen_dns,listen_port,flags,tls_accepted"
474 				" from autoreg_host"
475 				" where autoreg_hostid=" ZBX_FS_UI64,
476 				event->objectid);
477 
478 		if (NULL != (row = DBfetch(result)))
479 		{
480 			char			*sql = NULL;
481 			zbx_uint64_t		host_proxy_hostid;
482 			zbx_conn_flags_t	flags;
483 			int			flags_int;
484 			unsigned char		useip = 1;
485 			int			tls_accepted;
486 
487 			ZBX_DBROW2UINT64(proxy_hostid, row[0]);
488 			host_esc = DBdyn_escape_field("hosts", "host", row[1]);
489 			port = (unsigned short)atoi(row[4]);
490 			flags_int = atoi(row[5]);
491 
492 			switch (flags_int)
493 			{
494 				case ZBX_CONN_DEFAULT:
495 				case ZBX_CONN_IP:
496 				case ZBX_CONN_DNS:
497 					flags = (zbx_conn_flags_t)flags_int;
498 					break;
499 				default:
500 					flags = ZBX_CONN_DEFAULT;
501 					zabbix_log(LOG_LEVEL_WARNING, "wrong flags value: %d for host \"%s\":",
502 							flags_int, row[1]);
503 			}
504 
505 			if (ZBX_CONN_DNS == flags)
506 				useip = 0;
507 
508 			tls_accepted = atoi(row[6]);
509 
510 			result2 = DBselect(
511 					"select null"
512 					" from hosts"
513 					" where host='%s'"
514 						" and status=%d",
515 					host_esc, HOST_STATUS_TEMPLATE);
516 
517 			if (NULL != DBfetch(result2))
518 			{
519 				zabbix_log(LOG_LEVEL_WARNING, "cannot add discovered host \"%s\":"
520 						" template with the same name already exists", row[1]);
521 				DBfree_result(result2);
522 				goto out;
523 			}
524 			DBfree_result(result2);
525 
526 			sql = zbx_dsprintf(sql,
527 					"select hostid,proxy_hostid"
528 					" from hosts"
529 					" where host='%s'"
530 						" and flags<>%d"
531 						" and status in (%d,%d)"
532 					" order by hostid",
533 					host_esc, ZBX_FLAG_DISCOVERY_PROTOTYPE,
534 					HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED);
535 
536 			result2 = DBselectN(sql, 1);
537 
538 			zbx_free(sql);
539 
540 			if (NULL == (row2 = DBfetch(result2)))
541 			{
542 				hostid = DBget_maxid("hosts");
543 
544 				if (ZBX_TCP_SEC_TLS_PSK == tls_accepted)
545 				{
546 					char	psk_identity[HOST_TLS_PSK_IDENTITY_LEN_MAX];
547 					char	psk[HOST_TLS_PSK_LEN_MAX];
548 
549 					DCget_autoregistration_psk(psk_identity, sizeof(psk_identity),
550 							(unsigned char *)psk, sizeof(psk));
551 
552 					zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "proxy_hostid",
553 							"host", "name", "tls_connect", "tls_accept",
554 							"tls_psk_identity", "tls_psk", NULL);
555 					zbx_db_insert_add_values(&db_insert, hostid, proxy_hostid, row[1], row[1],
556 						tls_accepted, tls_accepted, psk_identity, psk);
557 				}
558 				else
559 				{
560 					zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "proxy_hostid", "host",
561 							"name", NULL);
562 					zbx_db_insert_add_values(&db_insert, hostid, proxy_hostid, row[1], row[1]);
563 				}
564 
565 				zbx_db_insert_execute(&db_insert);
566 				zbx_db_insert_clean(&db_insert);
567 
568 				if (HOST_INVENTORY_DISABLED != cfg.default_inventory_mode)
569 					DBadd_host_inventory(hostid, cfg.default_inventory_mode);
570 
571 				DBadd_interface(hostid, INTERFACE_TYPE_AGENT, useip, row[2], row[3], port, flags);
572 
573 				add_discovered_host_groups(hostid, &groupids);
574 			}
575 			else
576 			{
577 				ZBX_STR2UINT64(hostid, row2[0]);
578 				ZBX_DBROW2UINT64(host_proxy_hostid, row2[1]);
579 
580 				if (host_proxy_hostid != proxy_hostid)
581 				{
582 					DBexecute("update hosts"
583 							" set proxy_hostid=%s"
584 							" where hostid=" ZBX_FS_UI64,
585 							DBsql_id_ins(proxy_hostid), hostid);
586 				}
587 
588 				DBadd_interface(hostid, INTERFACE_TYPE_AGENT, useip, row[2], row[3], port, flags);
589 			}
590 			DBfree_result(result2);
591 out:
592 			zbx_free(host_esc);
593 		}
594 		DBfree_result(result);
595 	}
596 clean:
597 	zbx_config_clean(&cfg);
598 
599 	zbx_vector_uint64_destroy(&groupids);
600 
601 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
602 
603 	return hostid;
604 }
605 
606 /******************************************************************************
607  *                                                                            *
608  * Function: is_discovery_or_autoregistration                                 *
609  *                                                                            *
610  * Purpose: checks if the event is discovery or autoregistration event        *
611  *                                                                            *
612  * Return value: SUCCEED - it's discovery or autoregistration event           *
613  *               FAIL    - otherwise                                          *
614  *                                                                            *
615  ******************************************************************************/
is_discovery_or_autoregistration(const DB_EVENT * event)616 static int	is_discovery_or_autoregistration(const DB_EVENT *event)
617 {
618 	if (event->source == EVENT_SOURCE_DISCOVERY && (event->object == EVENT_OBJECT_DHOST ||
619 			event->object == EVENT_OBJECT_DSERVICE))
620 	{
621 		return SUCCEED;
622 	}
623 
624 	if (event->source == EVENT_SOURCE_AUTOREGISTRATION && event->object == EVENT_OBJECT_ZABBIX_ACTIVE)
625 		return SUCCEED;
626 
627 	return FAIL;
628 }
629 
630 /******************************************************************************
631  *                                                                            *
632  * Function: op_host_add                                                      *
633  *                                                                            *
634  * Purpose: add discovered host                                               *
635  *                                                                            *
636  * Parameters: trigger - trigger data                                         *
637  *             action  - action data                                          *
638  *                                                                            *
639  * Author: Alexei Vladishev                                                   *
640  *                                                                            *
641  ******************************************************************************/
op_host_add(const DB_EVENT * event)642 void	op_host_add(const DB_EVENT *event)
643 {
644 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
645 
646 	if (FAIL == is_discovery_or_autoregistration(event))
647 		return;
648 
649 	add_discovered_host(event);
650 
651 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
652 }
653 
654 /******************************************************************************
655  *                                                                            *
656  * Function: op_host_del                                                      *
657  *                                                                            *
658  * Purpose: delete host                                                       *
659  *                                                                            *
660  * Author: Eugene Grigorjev                                                   *
661  *                                                                            *
662  ******************************************************************************/
op_host_del(const DB_EVENT * event)663 void	op_host_del(const DB_EVENT *event)
664 {
665 	zbx_vector_uint64_t	hostids;
666 	zbx_uint64_t		hostid;
667 
668 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
669 
670 	if (FAIL == is_discovery_or_autoregistration(event))
671 		return;
672 
673 	if (0 == (hostid = select_discovered_host(event)))
674 		return;
675 
676 	zbx_vector_uint64_create(&hostids);
677 
678 	zbx_vector_uint64_append(&hostids, hostid);
679 
680 	DBdelete_hosts_with_prototypes(&hostids);
681 
682 	zbx_vector_uint64_destroy(&hostids);
683 
684 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
685 }
686 
687 /******************************************************************************
688  *                                                                            *
689  * Function: op_host_enable                                                   *
690  *                                                                            *
691  * Purpose: enable discovered                                                 *
692  *                                                                            *
693  * Author: Alexander Vladishev                                                *
694  *                                                                            *
695  ******************************************************************************/
op_host_enable(const DB_EVENT * event)696 void	op_host_enable(const DB_EVENT *event)
697 {
698 	zbx_uint64_t	hostid;
699 
700 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
701 
702 	if (FAIL == is_discovery_or_autoregistration(event))
703 		return;
704 
705 	if (0 == (hostid = add_discovered_host(event)))
706 		return;
707 
708 	DBexecute(
709 			"update hosts"
710 			" set status=%d"
711 			" where hostid=" ZBX_FS_UI64,
712 			HOST_STATUS_MONITORED,
713 			hostid);
714 
715 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
716 }
717 
718 /******************************************************************************
719  *                                                                            *
720  * Function: op_host_disable                                                  *
721  *                                                                            *
722  * Purpose: disable host                                                      *
723  *                                                                            *
724  * Author: Alexander Vladishev                                                *
725  *                                                                            *
726  ******************************************************************************/
op_host_disable(const DB_EVENT * event)727 void	op_host_disable(const DB_EVENT *event)
728 {
729 	zbx_uint64_t	hostid;
730 
731 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
732 
733 	if (FAIL == is_discovery_or_autoregistration(event))
734 		return;
735 
736 	if (0 == (hostid = add_discovered_host(event)))
737 		return;
738 
739 	DBexecute(
740 			"update hosts"
741 			" set status=%d"
742 			" where hostid=" ZBX_FS_UI64,
743 			HOST_STATUS_NOT_MONITORED,
744 			hostid);
745 
746 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
747 }
748 
749 /******************************************************************************
750  *                                                                            *
751  * Function: op_host_inventory_mode                                           *
752  *                                                                            *
753  * Purpose: sets host inventory mode                                          *
754  *                                                                            *
755  * Parameters: event          - [IN] the source event                         *
756  *             inventory_mode - [IN] the new inventory mode, see              *
757  *                              HOST_INVENTORY_ defines                       *
758  *                                                                            *
759  * Comments: This function does not allow disabling host inventory - only     *
760  *           setting manual or automatic host inventory mode is supported.    *
761  *                                                                            *
762  ******************************************************************************/
op_host_inventory_mode(const DB_EVENT * event,int inventory_mode)763 void	op_host_inventory_mode(const DB_EVENT *event, int inventory_mode)
764 {
765 	zbx_uint64_t	hostid;
766 
767 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
768 
769 	if (FAIL == is_discovery_or_autoregistration(event))
770 		return;
771 
772 	if (0 == (hostid = add_discovered_host(event)))
773 		return;
774 
775 	DBset_host_inventory(hostid, inventory_mode);
776 
777 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
778 }
779 
780 /******************************************************************************
781  *                                                                            *
782  * Function: op_groups_add                                                    *
783  *                                                                            *
784  * Purpose: add groups to discovered host                                     *
785  *                                                                            *
786  * Parameters: event    - [IN] event data                                     *
787  *             groupids - [IN] IDs of groups to add                           *
788  *                                                                            *
789  * Author: Alexei Vladishev                                                   *
790  *                                                                            *
791  ******************************************************************************/
op_groups_add(const DB_EVENT * event,zbx_vector_uint64_t * groupids)792 void	op_groups_add(const DB_EVENT *event, zbx_vector_uint64_t *groupids)
793 {
794 	zbx_uint64_t	hostid;
795 
796 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
797 
798 	if (FAIL == is_discovery_or_autoregistration(event))
799 		return;
800 
801 	if (0 == (hostid = add_discovered_host(event)))
802 		return;
803 
804 	add_discovered_host_groups(hostid, groupids);
805 
806 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
807 }
808 
809 /******************************************************************************
810  *                                                                            *
811  * Function: op_groups_del                                                    *
812  *                                                                            *
813  * Purpose: delete groups from discovered host                                *
814  *                                                                            *
815  * Parameters: event    - [IN] event data                                     *
816  *             groupids - [IN] IDs of groups to delete                        *
817  *                                                                            *
818  * Author: Alexei Vladishev                                                   *
819  *                                                                            *
820  ******************************************************************************/
op_groups_del(const DB_EVENT * event,zbx_vector_uint64_t * groupids)821 void	op_groups_del(const DB_EVENT *event, zbx_vector_uint64_t *groupids)
822 {
823 	DB_RESULT	result;
824 	zbx_uint64_t	hostid;
825 	char		*sql = NULL;
826 	size_t		sql_alloc = 256, sql_offset = 0;
827 
828 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
829 
830 	if (FAIL == is_discovery_or_autoregistration(event))
831 		return;
832 
833 	if (0 == (hostid = select_discovered_host(event)))
834 		return;
835 
836 	sql = (char *)zbx_malloc(sql, sql_alloc);
837 
838 	/* make sure host belongs to at least one hostgroup */
839 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
840 			"select groupid"
841 			" from hosts_groups"
842 			" where hostid=" ZBX_FS_UI64
843 				" and not",
844 			hostid);
845 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
846 
847 	result = DBselectN(sql, 1);
848 
849 	if (NULL == DBfetch(result))
850 	{
851 		zabbix_log(LOG_LEVEL_WARNING, "cannot remove host \"%s\" from all host groups:"
852 				" it must belong to at least one", zbx_host_string(hostid));
853 	}
854 	else
855 	{
856 		sql_offset = 0;
857 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
858 				"delete from hosts_groups"
859 				" where hostid=" ZBX_FS_UI64
860 					" and",
861 				hostid);
862 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
863 
864 		DBexecute("%s", sql);
865 	}
866 	DBfree_result(result);
867 
868 	zbx_free(sql);
869 
870 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
871 }
872 
873 /******************************************************************************
874  *                                                                            *
875  * Function: op_template_add                                                  *
876  *                                                                            *
877  * Purpose: link host with template                                           *
878  *                                                                            *
879  * Parameters: event           - [IN] event data                              *
880  *             lnk_templateids - [IN] array of template IDs                   *
881  *                                                                            *
882  * Author: Eugene Grigorjev                                                   *
883  *                                                                            *
884  ******************************************************************************/
op_template_add(const DB_EVENT * event,zbx_vector_uint64_t * lnk_templateids)885 void	op_template_add(const DB_EVENT *event, zbx_vector_uint64_t *lnk_templateids)
886 {
887 	zbx_uint64_t	hostid;
888 	char		*error;
889 
890 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
891 
892 	if (FAIL == is_discovery_or_autoregistration(event))
893 		return;
894 
895 	if (0 == (hostid = add_discovered_host(event)))
896 		return;
897 
898 	if (SUCCEED != DBcopy_template_elements(hostid, lnk_templateids, &error))
899 	{
900 		zabbix_log(LOG_LEVEL_WARNING, "cannot link template(s) %s", error);
901 		zbx_free(error);
902 	}
903 
904 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
905 }
906 
907 /******************************************************************************
908  *                                                                            *
909  * Function: op_template_del                                                  *
910  *                                                                            *
911  * Purpose: unlink and clear host from template                               *
912  *                                                                            *
913  * Parameters: event           - [IN] event data                              *
914  *             lnk_templateids - [IN] array of template IDs                   *
915  *                                                                            *
916  * Author: Eugene Grigorjev                                                   *
917  *                                                                            *
918  ******************************************************************************/
op_template_del(const DB_EVENT * event,zbx_vector_uint64_t * del_templateids)919 void	op_template_del(const DB_EVENT *event, zbx_vector_uint64_t *del_templateids)
920 {
921 	zbx_uint64_t	hostid;
922 	char		*error;
923 
924 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
925 
926 	if (FAIL == is_discovery_or_autoregistration(event))
927 		return;
928 
929 	if (0 == (hostid = select_discovered_host(event)))
930 		return;
931 
932 	if (SUCCEED != DBdelete_template_elements(hostid, del_templateids, &error))
933 	{
934 		zabbix_log(LOG_LEVEL_WARNING, "cannot unlink template: %s", error);
935 		zbx_free(error);
936 	}
937 
938 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
939 }
940