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 "db.h"
22 #include "dbcache.h"
23 #include "log.h"
24 #include "zbxserver.h"
25 #include "zbxregexp.h"
26 #include "zbxcompress.h"
27
28 #include "../../libs/zbxcrypto/tls_tcp_active.h"
29
30 #include "active.h"
31
32 extern unsigned char program_type;
33
34 /******************************************************************************
35 * *
36 * Function: db_register_host *
37 * *
38 * Purpose: perform active agent auto registration *
39 * *
40 * Parameters: host - [IN] name of the host to be added or updated *
41 * ip - [IN] IP address of the host *
42 * port - [IN] port of the host *
43 * connection_type - [IN] ZBX_TCP_SEC_UNENCRYPTED, *
44 * ZBX_TCP_SEC_TLS_PSK or ZBX_TCP_SEC_TLS_CERT *
45 * host_metadata - [IN] host metadata *
46 * flag - [IN] flag describing interface type *
47 * interface - [IN] interface value if flag is not default *
48 * *
49 * Comments: helper function for get_hostid_by_host *
50 * *
51 ******************************************************************************/
db_register_host(const char * host,const char * ip,unsigned short port,unsigned int connection_type,const char * host_metadata,zbx_conn_flags_t flag,const char * interface)52 static void db_register_host(const char *host, const char *ip, unsigned short port, unsigned int connection_type,
53 const char *host_metadata, zbx_conn_flags_t flag, const char *interface)
54 {
55 char dns[INTERFACE_DNS_LEN_MAX];
56 char ip_addr[INTERFACE_IP_LEN_MAX];
57 const char *p;
58 const char *p_ip, *p_dns;
59
60 p_ip = ip;
61 p_dns = dns;
62
63 if (ZBX_CONN_DEFAULT == flag)
64 p = ip;
65 else if (ZBX_CONN_IP == flag)
66 p_ip = p = interface;
67
68 zbx_alarm_on(CONFIG_TIMEOUT);
69 if (ZBX_CONN_DEFAULT == flag || ZBX_CONN_IP == flag)
70 {
71 if (0 == strncmp("::ffff:", p, 7) && SUCCEED == is_ip4(p + 7))
72 p += 7;
73
74 zbx_gethost_by_ip(p, dns, sizeof(dns));
75 }
76 else if (ZBX_CONN_DNS == flag)
77 {
78 zbx_getip_by_host(interface, ip_addr, sizeof(ip_addr));
79 p_ip = ip_addr;
80 p_dns = interface;
81 }
82 zbx_alarm_off();
83
84 DBbegin();
85
86 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
87 {
88 DBregister_host(0, host, p_ip, p_dns, port, connection_type, host_metadata, (unsigned short)flag,
89 (int)time(NULL));
90 }
91 else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY))
92 DBproxy_register_host(host, p_ip, p_dns, port, connection_type, host_metadata, (unsigned short)flag);
93
94 DBcommit();
95 }
96
zbx_autoreg_check_permissions(const char * host,const char * ip,unsigned short port,const zbx_socket_t * sock)97 static int zbx_autoreg_check_permissions(const char *host, const char *ip, unsigned short port,
98 const zbx_socket_t *sock)
99 {
100 zbx_config_t cfg;
101 int ret = FAIL;
102
103 zbx_config_get(&cfg, ZBX_CONFIG_FLAGS_AUTOREG_TLS_ACCEPT);
104
105 if (0 == (cfg.autoreg_tls_accept & sock->connection_type))
106 {
107 zabbix_log(LOG_LEVEL_WARNING, "autoregistration from \"%s\" denied (host:\"%s\" ip:\"%s\""
108 " port:%hu): connection type \"%s\" is not allowed for autoregistration",
109 sock->peer, host, ip, port, zbx_tcp_connection_type_name(sock->connection_type));
110 goto out;
111 }
112
113 #if defined(HAVE_GNUTLS) || (defined(HAVE_OPENSSL) && defined(HAVE_OPENSSL_WITH_PSK))
114 if (ZBX_TCP_SEC_TLS_PSK == sock->connection_type)
115 {
116 if (0 == (ZBX_PSK_FOR_AUTOREG & zbx_tls_get_psk_usage()))
117 {
118 zabbix_log(LOG_LEVEL_WARNING, "autoregistration from \"%s\" denied (host:\"%s\" ip:\"%s\""
119 " port:%hu): connection used PSK which is not configured for autoregistration",
120 sock->peer, host, ip, port);
121 goto out;
122 }
123
124 ret = SUCCEED;
125 }
126 else if (ZBX_TCP_SEC_UNENCRYPTED == sock->connection_type)
127 {
128 ret = SUCCEED;
129 }
130 else
131 THIS_SHOULD_NEVER_HAPPEN;
132 #else
133 ret = SUCCEED;
134 #endif
135 out:
136 zbx_config_clean(&cfg);
137
138 return ret;
139 }
140
141 /******************************************************************************
142 * *
143 * Function: get_hostid_by_host *
144 * *
145 * Purpose: check for host name and return hostid *
146 * *
147 * Parameters: sock - [IN] open socket of server-agent connection *
148 * host - [IN] host name *
149 * ip - [IN] IP address of the host *
150 * port - [IN] port of the host *
151 * host_metadata - [IN] host metadata *
152 * flag - [IN] flag describing interface type *
153 * interface - [IN] interface value if flag is not default *
154 * hostid - [OUT] host ID *
155 * error - [OUT] error message *
156 * *
157 * Return value: SUCCEED - host is found *
158 * FAIL - an error occurred or host not found *
159 * *
160 * Author: Alexander Vladishev *
161 * *
162 * Comments: NB! adds host to the database if it does not exist or if it *
163 * exists but metadata, interface, interface type or port has *
164 * changed *
165 * *
166 ******************************************************************************/
get_hostid_by_host(const zbx_socket_t * sock,const char * host,const char * ip,unsigned short port,const char * host_metadata,zbx_conn_flags_t flag,const char * interface,zbx_uint64_t * hostid,char * error)167 static int get_hostid_by_host(const zbx_socket_t *sock, const char *host, const char *ip, unsigned short port,
168 const char *host_metadata, zbx_conn_flags_t flag, const char *interface, zbx_uint64_t *hostid,
169 char *error)
170 {
171 char *host_esc, *ch_error, *old_metadata, *old_ip, *old_dns, *old_flag, *old_port;
172 DB_RESULT result;
173 DB_ROW row;
174 unsigned short old_port_v;
175 int tls_offset = 0, ret = FAIL;
176 zbx_conn_flags_t old_flag_v;
177
178 zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:'%s' metadata:'%s'", __func__, host, host_metadata);
179
180 if (FAIL == zbx_check_hostname(host, &ch_error))
181 {
182 zbx_snprintf(error, MAX_STRING_LEN, "invalid host name [%s]: %s", host, ch_error);
183 zbx_free(ch_error);
184 goto out;
185 }
186
187 host_esc = DBdyn_escape_string(host);
188
189 result =
190 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
191 DBselect(
192 "select h.hostid,h.status,h.tls_accept,h.tls_issuer,h.tls_subject,h.tls_psk_identity,"
193 "a.host_metadata,a.listen_ip,a.listen_dns,a.listen_port,a.flags"
194 " from hosts h"
195 " left join autoreg_host a"
196 " on a.proxy_hostid is null and a.host=h.host"
197 " where h.host='%s'"
198 " and h.status in (%d,%d)"
199 " and h.flags<>%d"
200 " and h.proxy_hostid is null",
201 host_esc, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, ZBX_FLAG_DISCOVERY_PROTOTYPE);
202 #else
203 DBselect(
204 "select h.hostid,h.status,h.tls_accept,a.host_metadata,a.listen_ip,a.listen_dns,a.listen_port,"
205 "a.flags"
206 " from hosts h"
207 " left join autoreg_host a"
208 " on a.proxy_hostid is null and a.host=h.host"
209 " where h.host='%s'"
210 " and h.status in (%d,%d)"
211 " and h.flags<>%d"
212 " and h.proxy_hostid is null",
213 host_esc, HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, ZBX_FLAG_DISCOVERY_PROTOTYPE);
214 #endif
215 if (NULL != (row = DBfetch(result)))
216 {
217 if (0 == ((unsigned int)atoi(row[2]) & sock->connection_type))
218 {
219 zbx_snprintf(error, MAX_STRING_LEN, "connection of type \"%s\" is not allowed for host"
220 " \"%s\"", zbx_tcp_connection_type_name(sock->connection_type), host);
221 goto done;
222 }
223
224 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
225 if (ZBX_TCP_SEC_TLS_CERT == sock->connection_type)
226 {
227 zbx_tls_conn_attr_t attr;
228
229 if (SUCCEED != zbx_tls_get_attr_cert(sock, &attr))
230 {
231 THIS_SHOULD_NEVER_HAPPEN;
232
233 zbx_snprintf(error, MAX_STRING_LEN, "cannot get connection attributes for host"
234 " \"%s\"", host);
235 goto done;
236 }
237
238 /* simplified match, not compliant with RFC 4517, 4518 */
239 if ('\0' != *row[3] && 0 != strcmp(row[3], attr.issuer))
240 {
241 zbx_snprintf(error, MAX_STRING_LEN, "certificate issuer does not match for"
242 " host \"%s\"", host);
243 goto done;
244 }
245
246 /* simplified match, not compliant with RFC 4517, 4518 */
247 if ('\0' != *row[4] && 0 != strcmp(row[4], attr.subject))
248 {
249 zbx_snprintf(error, MAX_STRING_LEN, "certificate subject does not match for"
250 " host \"%s\"", host);
251 goto done;
252 }
253 }
254 #if defined(HAVE_GNUTLS) || (defined(HAVE_OPENSSL) && defined(HAVE_OPENSSL_WITH_PSK))
255 else if (ZBX_TCP_SEC_TLS_PSK == sock->connection_type)
256 {
257 zbx_tls_conn_attr_t attr;
258
259 if (SUCCEED != zbx_tls_get_attr_psk(sock, &attr))
260 {
261 THIS_SHOULD_NEVER_HAPPEN;
262
263 zbx_snprintf(error, MAX_STRING_LEN, "cannot get connection attributes for host"
264 " \"%s\"", host);
265 goto done;
266 }
267
268 if (strlen(row[5]) != attr.psk_identity_len ||
269 0 != memcmp(row[5], attr.psk_identity, attr.psk_identity_len))
270 {
271 zbx_snprintf(error, MAX_STRING_LEN, "false PSK identity for host \"%s\"", host);
272 goto done;
273 }
274 }
275 #endif
276 tls_offset = 3;
277 #endif
278 old_metadata = row[3 + tls_offset];
279 old_ip = row[4 + tls_offset];
280 old_dns = row[5 + tls_offset];
281 old_port = row[6 + tls_offset];
282 old_flag = row[7 + tls_offset];
283 old_port_v = (unsigned short)(SUCCEED == DBis_null(old_port)) ? 0 : atoi(old_port);
284 old_flag_v = (zbx_conn_flags_t)(SUCCEED == DBis_null(old_flag)) ? ZBX_CONN_DEFAULT : atoi(old_flag);
285 /* metadata is available only on Zabbix server */
286 if (SUCCEED == DBis_null(old_flag) || 0 != strcmp(old_metadata, host_metadata) ||
287 (ZBX_CONN_IP == flag && ( 0 != strcmp(old_ip, interface) || old_port_v != port)) ||
288 (ZBX_CONN_DNS == flag && ( 0 != strcmp(old_dns, interface) || old_port_v != port)) ||
289 (old_flag_v != flag))
290 {
291 db_register_host(host, ip, port, sock->connection_type, host_metadata, flag, interface);
292 }
293
294 if (HOST_STATUS_MONITORED != atoi(row[1]))
295 {
296 zbx_snprintf(error, MAX_STRING_LEN, "host [%s] not monitored", host);
297 goto done;
298 }
299
300 ZBX_STR2UINT64(*hostid, row[0]);
301 ret = SUCCEED;
302 }
303 else
304 {
305 zbx_snprintf(error, MAX_STRING_LEN, "host [%s] not found", host);
306
307 if (SUCCEED == zbx_autoreg_check_permissions(host, ip, port, sock))
308 db_register_host(host, ip, port, sock->connection_type, host_metadata, flag, interface);
309 }
310 done:
311 DBfree_result(result);
312
313 zbx_free(host_esc);
314 out:
315 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
316
317 return ret;
318 }
319
get_list_of_active_checks(zbx_uint64_t hostid,zbx_vector_uint64_t * itemids)320 static void get_list_of_active_checks(zbx_uint64_t hostid, zbx_vector_uint64_t *itemids)
321 {
322 DB_RESULT result;
323 DB_ROW row;
324 zbx_uint64_t itemid;
325
326 result = DBselect(
327 "select itemid"
328 " from items"
329 " where type=%d"
330 " and flags<>%d"
331 " and hostid=" ZBX_FS_UI64,
332 ITEM_TYPE_ZABBIX_ACTIVE, ZBX_FLAG_DISCOVERY_PROTOTYPE, hostid);
333
334 while (NULL != (row = DBfetch(result)))
335 {
336 ZBX_STR2UINT64(itemid, row[0]);
337 zbx_vector_uint64_append(itemids, itemid);
338 }
339 DBfree_result(result);
340 }
341
342 /******************************************************************************
343 * *
344 * Function: send_list_of_active_checks *
345 * *
346 * Purpose: send list of active checks to the host (older version agent) *
347 * *
348 * Parameters: sock - open socket of server-agent connection *
349 * request - request buffer *
350 * *
351 * Return value: SUCCEED - list of active checks sent successfully *
352 * FAIL - an error occurred *
353 * *
354 * Comments: format of the request: ZBX_GET_ACTIVE_CHECKS\n<host name>\n *
355 * format of the list: key:delay:last_log_size *
356 * *
357 ******************************************************************************/
send_list_of_active_checks(zbx_socket_t * sock,char * request)358 int send_list_of_active_checks(zbx_socket_t *sock, char *request)
359 {
360 char *host = NULL, *p, *buffer = NULL, error[MAX_STRING_LEN];
361 size_t buffer_alloc = 8 * ZBX_KIBIBYTE, buffer_offset = 0;
362 int ret = FAIL, i;
363 zbx_uint64_t hostid;
364 zbx_vector_uint64_t itemids;
365
366 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
367
368 if (NULL != (host = strchr(request, '\n')))
369 {
370 host++;
371 if (NULL != (p = strchr(host, '\n')))
372 *p = '\0';
373 }
374 else
375 {
376 zbx_snprintf(error, sizeof(error), "host is null");
377 goto out;
378 }
379
380 /* no host metadata in older versions of agent */
381 if (FAIL == get_hostid_by_host(sock, host, sock->peer, ZBX_DEFAULT_AGENT_PORT, "", 0, "", &hostid, error))
382 goto out;
383
384 zbx_vector_uint64_create(&itemids);
385
386 get_list_of_active_checks(hostid, &itemids);
387
388 buffer = (char *)zbx_malloc(buffer, buffer_alloc);
389
390 if (0 != itemids.values_num)
391 {
392 DC_ITEM *dc_items;
393 int *errcodes;
394
395 dc_items = (DC_ITEM *)zbx_malloc(NULL, sizeof(DC_ITEM) * itemids.values_num);
396 errcodes = (int *)zbx_malloc(NULL, sizeof(int) * itemids.values_num);
397
398 DCconfig_get_items_by_itemids(dc_items, itemids.values, errcodes, itemids.values_num);
399
400 for (i = 0; i < itemids.values_num; i++)
401 {
402 int delay;
403
404 if (SUCCEED != errcodes[i])
405 {
406 zabbix_log(LOG_LEVEL_DEBUG, "%s() Item [" ZBX_FS_UI64 "] was not found in the"
407 " server cache. Not sending now.", __func__, itemids.values[i]);
408 continue;
409 }
410
411 if (ITEM_STATUS_ACTIVE != dc_items[i].status)
412 continue;
413
414 if (HOST_STATUS_MONITORED != dc_items[i].host.status)
415 continue;
416
417 if (SUCCEED != zbx_interval_preproc(dc_items[i].delay, &delay, NULL, NULL))
418 continue;
419
420 zbx_snprintf_alloc(&buffer, &buffer_alloc, &buffer_offset, "%s:%d:" ZBX_FS_UI64 "\n",
421 dc_items[i].key_orig, delay, dc_items[i].lastlogsize);
422 }
423
424 DCconfig_clean_items(dc_items, errcodes, itemids.values_num);
425
426 zbx_free(errcodes);
427 zbx_free(dc_items);
428 }
429
430 zbx_vector_uint64_destroy(&itemids);
431
432 zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, "ZBX_EOF\n");
433
434 zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __func__, buffer);
435
436 zbx_alarm_on(CONFIG_TIMEOUT);
437 if (SUCCEED != zbx_tcp_send_raw(sock, buffer))
438 zbx_strlcpy(error, zbx_socket_strerror(), MAX_STRING_LEN);
439 else
440 ret = SUCCEED;
441 zbx_alarm_off();
442
443 zbx_free(buffer);
444 out:
445 if (FAIL == ret)
446 zabbix_log(LOG_LEVEL_WARNING, "cannot send list of active checks to \"%s\": %s", sock->peer, error);
447
448 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
449
450 return ret;
451 }
452
453 /******************************************************************************
454 * *
455 * Function: zbx_vector_str_append_uniq *
456 * *
457 * Purpose: append non duplicate string to the string vector *
458 * *
459 * Parameters: vector - [IN/OUT] the string vector *
460 * str - [IN] the string to append *
461 * *
462 ******************************************************************************/
zbx_vector_str_append_uniq(zbx_vector_str_t * vector,const char * str)463 static void zbx_vector_str_append_uniq(zbx_vector_str_t *vector, const char *str)
464 {
465 if (FAIL == zbx_vector_str_search(vector, str, ZBX_DEFAULT_STR_COMPARE_FUNC))
466 zbx_vector_str_append(vector, zbx_strdup(NULL, str));
467 }
468
469 /******************************************************************************
470 * *
471 * Function: zbx_itemkey_extract_global_regexps *
472 * *
473 * Purpose: extract global regular expression names from item key *
474 * *
475 * Parameters: key - [IN] the item key to parse *
476 * regexps - [OUT] the extracted regular expression names *
477 * *
478 ******************************************************************************/
zbx_itemkey_extract_global_regexps(const char * key,zbx_vector_str_t * regexps)479 static void zbx_itemkey_extract_global_regexps(const char *key, zbx_vector_str_t *regexps)
480 {
481 #define ZBX_KEY_LOG 1
482 #define ZBX_KEY_EVENTLOG 2
483
484 AGENT_REQUEST request;
485 int item_key;
486 const char *param;
487
488 if (0 == strncmp(key, "log[", 4) || 0 == strncmp(key, "logrt[", 6) || 0 == strncmp(key, "log.count[", 10) ||
489 0 == strncmp(key, "logrt.count[", 12))
490 item_key = ZBX_KEY_LOG;
491 else if (0 == strncmp(key, "eventlog[", 9))
492 item_key = ZBX_KEY_EVENTLOG;
493 else
494 return;
495
496 init_request(&request);
497
498 if(SUCCEED != parse_item_key(key, &request))
499 goto out;
500
501 /* "params" parameter */
502 if (NULL != (param = get_rparam(&request, 1)) && '@' == *param)
503 zbx_vector_str_append_uniq(regexps, param + 1);
504
505 if (ZBX_KEY_EVENTLOG == item_key)
506 {
507 /* "severity" parameter */
508 if (NULL != (param = get_rparam(&request, 2)) && '@' == *param)
509 zbx_vector_str_append_uniq(regexps, param + 1);
510
511 /* "source" parameter */
512 if (NULL != (param = get_rparam(&request, 3)) && '@' == *param)
513 zbx_vector_str_append_uniq(regexps, param + 1);
514
515 /* "logeventid" parameter */
516 if (NULL != (param = get_rparam(&request, 4)) && '@' == *param)
517 zbx_vector_str_append_uniq(regexps, param + 1);
518 }
519 out:
520 free_request(&request);
521 }
522
523 /******************************************************************************
524 * *
525 * Function: send_list_of_active_checks_json *
526 * *
527 * Purpose: send list of active checks to the host *
528 * *
529 * Parameters: sock - open socket of server-agent connection *
530 * jp - request buffer *
531 * *
532 * Return value: SUCCEED - list of active checks sent successfully *
533 * FAIL - an error occurred *
534 * *
535 * Author: Alexander Vladishev *
536 * *
537 ******************************************************************************/
send_list_of_active_checks_json(zbx_socket_t * sock,struct zbx_json_parse * jp)538 int send_list_of_active_checks_json(zbx_socket_t *sock, struct zbx_json_parse *jp)
539 {
540 char host[HOST_HOST_LEN_MAX], tmp[MAX_STRING_LEN], ip[INTERFACE_IP_LEN_MAX],
541 error[MAX_STRING_LEN], *host_metadata = NULL, *interface = NULL, *buffer = NULL;
542 struct zbx_json json;
543 int ret = FAIL, i, version;
544 zbx_uint64_t hostid;
545 size_t host_metadata_alloc = 1; /* for at least NUL-termination char */
546 size_t interface_alloc = 1; /* for at least NUL-termination char */
547 size_t buffer_size, reserved = 0;
548 unsigned short port;
549 zbx_vector_uint64_t itemids;
550 zbx_conn_flags_t flag = ZBX_CONN_DEFAULT;
551
552 zbx_vector_ptr_t regexps;
553 zbx_vector_str_t names;
554
555 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
556
557 zbx_vector_ptr_create(®exps);
558 zbx_vector_str_create(&names);
559
560 if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOST, host, sizeof(host), NULL))
561 {
562 zbx_snprintf(error, MAX_STRING_LEN, "%s", zbx_json_strerror());
563 goto error;
564 }
565
566 host_metadata = (char *)zbx_malloc(host_metadata, host_metadata_alloc);
567
568 if (FAIL == zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_HOST_METADATA,
569 &host_metadata, &host_metadata_alloc, NULL))
570 {
571 *host_metadata = '\0';
572 }
573
574 interface = (char *)zbx_malloc(interface, interface_alloc);
575
576 if (FAIL == zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_INTERFACE, &interface, &interface_alloc, NULL))
577 {
578 *interface = '\0';
579 }
580 else if (SUCCEED == is_ip(interface))
581 {
582 flag = ZBX_CONN_IP;
583 }
584 else if (SUCCEED == zbx_validate_hostname(interface))
585 {
586 flag = ZBX_CONN_DNS;
587 }
588 else
589 {
590 zbx_snprintf(error, MAX_STRING_LEN, "\"%s\" is not a valid IP or DNS", interface);
591 goto error;
592 }
593
594 if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_IP, ip, sizeof(ip), NULL))
595 strscpy(ip, sock->peer);
596
597 if (FAIL == is_ip(ip)) /* check even if 'ip' came from get_ip_by_socket() - it can return not a valid IP */
598 {
599 zbx_snprintf(error, MAX_STRING_LEN, "\"%s\" is not a valid IP address", ip);
600 goto error;
601 }
602
603 if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_PORT, tmp, sizeof(tmp), NULL))
604 {
605 port = ZBX_DEFAULT_AGENT_PORT;
606 }
607 else if (FAIL == is_ushort(tmp, &port))
608 {
609 zbx_snprintf(error, MAX_STRING_LEN, "\"%s\" is not a valid port", tmp);
610 goto error;
611 }
612
613 if (FAIL == get_hostid_by_host(sock, host, ip, port, host_metadata, flag, interface, &hostid, error))
614 goto error;
615
616 if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_VERSION, tmp, sizeof(tmp), NULL) ||
617 FAIL == (version = zbx_get_component_version(tmp)))
618 {
619 version = ZBX_COMPONENT_VERSION(4, 2);
620 }
621
622 zbx_vector_uint64_create(&itemids);
623
624 get_list_of_active_checks(hostid, &itemids);
625
626 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
627 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
628 zbx_json_addarray(&json, ZBX_PROTO_TAG_DATA);
629
630 if (0 != itemids.values_num)
631 {
632 DC_ITEM *dc_items;
633 int *errcodes, delay;
634
635 dc_items = (DC_ITEM *)zbx_malloc(NULL, sizeof(DC_ITEM) * itemids.values_num);
636 errcodes = (int *)zbx_malloc(NULL, sizeof(int) * itemids.values_num);
637
638 DCconfig_get_items_by_itemids(dc_items, itemids.values, errcodes, itemids.values_num);
639
640 for (i = 0; i < itemids.values_num; i++)
641 {
642 if (SUCCEED != errcodes[i])
643 {
644 zabbix_log(LOG_LEVEL_DEBUG, "%s() Item [" ZBX_FS_UI64 "] was not found in the"
645 " server cache. Not sending now.", __func__, itemids.values[i]);
646 continue;
647 }
648
649 if (ITEM_STATUS_ACTIVE != dc_items[i].status)
650 continue;
651
652 if (HOST_STATUS_MONITORED != dc_items[i].host.status)
653 continue;
654
655 if (SUCCEED != zbx_interval_preproc(dc_items[i].delay, &delay, NULL, NULL))
656 continue;
657
658
659 dc_items[i].key = zbx_strdup(dc_items[i].key, dc_items[i].key_orig);
660 substitute_key_macros_unmasked(&dc_items[i].key, NULL, &dc_items[i], NULL, NULL,
661 MACRO_TYPE_ITEM_KEY, NULL, 0);
662
663 zbx_json_addobject(&json, NULL);
664 zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY, dc_items[i].key, ZBX_JSON_TYPE_STRING);
665
666 if (ZBX_COMPONENT_VERSION(4,4) > version)
667 {
668 if (0 != strcmp(dc_items[i].key, dc_items[i].key_orig))
669 {
670 zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY_ORIG,
671 dc_items[i].key_orig, ZBX_JSON_TYPE_STRING);
672 }
673
674 zbx_json_adduint64(&json, ZBX_PROTO_TAG_DELAY, delay);
675 }
676 else
677 {
678 zbx_json_adduint64(&json, ZBX_PROTO_TAG_ITEMID, dc_items[i].itemid);
679 zbx_json_addstring(&json, ZBX_PROTO_TAG_DELAY, dc_items[i].delay, ZBX_JSON_TYPE_STRING);
680 }
681
682 /* The agent expects ALWAYS to have lastlogsize and mtime tags. */
683 /* Removing those would cause older agents to fail. */
684 zbx_json_adduint64(&json, ZBX_PROTO_TAG_LASTLOGSIZE, dc_items[i].lastlogsize);
685 zbx_json_adduint64(&json, ZBX_PROTO_TAG_MTIME, dc_items[i].mtime);
686 zbx_json_close(&json);
687
688 zbx_itemkey_extract_global_regexps(dc_items[i].key, &names);
689
690 zbx_free(dc_items[i].key);
691 }
692
693 DCconfig_clean_items(dc_items, errcodes, itemids.values_num);
694
695 zbx_free(errcodes);
696 zbx_free(dc_items);
697 }
698
699 zbx_json_close(&json);
700
701 if (ZBX_COMPONENT_VERSION(4,4) == version || ZBX_COMPONENT_VERSION(5,0) == version)
702 zbx_json_adduint64(&json, ZBX_PROTO_TAG_REFRESH_UNSUPPORTED, 600);
703
704 zbx_vector_uint64_destroy(&itemids);
705
706 DCget_expressions_by_names(®exps, (const char * const *)names.values, names.values_num);
707
708 if (0 < regexps.values_num)
709 {
710 char str[32];
711
712 zbx_json_addarray(&json, ZBX_PROTO_TAG_REGEXP);
713
714 for (i = 0; i < regexps.values_num; i++)
715 {
716 zbx_expression_t *regexp = (zbx_expression_t *)regexps.values[i];
717
718 zbx_json_addobject(&json, NULL);
719 zbx_json_addstring(&json, "name", regexp->name, ZBX_JSON_TYPE_STRING);
720 zbx_json_addstring(&json, "expression", regexp->expression, ZBX_JSON_TYPE_STRING);
721
722 zbx_snprintf(str, sizeof(str), "%d", regexp->expression_type);
723 zbx_json_addstring(&json, "expression_type", str, ZBX_JSON_TYPE_INT);
724
725 zbx_snprintf(str, sizeof(str), "%c", regexp->exp_delimiter);
726 zbx_json_addstring(&json, "exp_delimiter", str, ZBX_JSON_TYPE_STRING);
727
728 zbx_snprintf(str, sizeof(str), "%d", regexp->case_sensitive);
729 zbx_json_addstring(&json, "case_sensitive", str, ZBX_JSON_TYPE_INT);
730
731 zbx_json_close(&json);
732 }
733
734 zbx_json_close(&json);
735 }
736
737 zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __func__, json.buffer);
738
739 if (0 != (ZBX_TCP_COMPRESS & sock->protocol))
740 {
741 if (SUCCEED != zbx_compress(json.buffer, json.buffer_size, &buffer, &buffer_size))
742 {
743 zbx_snprintf(error, MAX_STRING_LEN, "cannot compress data: %s", zbx_compress_strerror());
744 goto error;
745 }
746
747 reserved = json.buffer_size;
748 zbx_json_free(&json); /* json buffer can be large, free as fast as possible */
749
750 if (SUCCEED != (ret = zbx_tcp_send_ext(sock, buffer, buffer_size, reserved, sock->protocol,
751 CONFIG_TIMEOUT)))
752 {
753 strscpy(error, zbx_socket_strerror());
754 }
755 }
756 else
757 {
758 if (SUCCEED != (ret = zbx_tcp_send_ext(sock, json.buffer, json.buffer_size, 0, sock->protocol,
759 CONFIG_TIMEOUT)))
760 {
761 strscpy(error, zbx_socket_strerror());
762 }
763 }
764
765 zbx_json_free(&json);
766
767 goto out;
768 error:
769 zabbix_log(LOG_LEVEL_WARNING, "cannot send list of active checks to \"%s\": %s", sock->peer, error);
770
771 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
772 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING);
773 zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, error, ZBX_JSON_TYPE_STRING);
774
775 zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __func__, json.buffer);
776
777 ret = zbx_tcp_send(sock, json.buffer);
778
779 zbx_json_free(&json);
780 out:
781 for (i = 0; i < names.values_num; i++)
782 zbx_free(names.values[i]);
783
784 zbx_vector_str_destroy(&names);
785
786 zbx_regexp_clean_expressions(®exps);
787 zbx_vector_ptr_destroy(®exps);
788
789 zbx_free(host_metadata);
790 zbx_free(interface);
791 zbx_free(buffer);
792
793 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
794
795 return ret;
796 }
797