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
22 #include "comms.h"
23 #include "log.h"
24 #include "zbxjson.h"
25 #include "zbxserver.h"
26 #include "dbcache.h"
27 #include "proxy.h"
28 #include "zbxself.h"
29
30 #include "trapper.h"
31 #include "active.h"
32 #include "nodecommand.h"
33 #include "proxyconfig.h"
34 #include "proxydiscovery.h"
35 #include "proxyautoreg.h"
36 #include "proxyhosts.h"
37 #include "proxydata.h"
38
39 #include "daemon.h"
40 #include "../../libs/zbxcrypto/tls.h"
41 #include "../../libs/zbxserver/zabbix_stats.h"
42
43 #define ZBX_MAX_SECTION_ENTRIES 4
44 #define ZBX_MAX_ENTRY_ATTRIBUTES 3
45
46 extern unsigned char process_type, program_type;
47 extern int server_num, process_num;
48 extern size_t (*find_psk_in_cache)(const unsigned char *, unsigned char *, size_t);
49
50 extern int CONFIG_CONFSYNCER_FORKS;
51
52 typedef struct
53 {
54 zbx_counter_value_t online;
55 zbx_counter_value_t offline;
56 }
57 zbx_user_stats_t;
58
59 typedef union
60 {
61 zbx_counter_value_t counter; /* single global counter */
62 zbx_vector_ptr_t counters; /* array of per proxy counters */
63 }
64 zbx_entry_info_t;
65
66 typedef struct
67 {
68 const char *name;
69 zbx_uint64_t value;
70 }
71 zbx_entry_attribute_t;
72
73 typedef struct
74 {
75 zbx_entry_info_t *info;
76 zbx_counter_type_t counter_type;
77 zbx_entry_attribute_t attributes[ZBX_MAX_ENTRY_ATTRIBUTES];
78 }
79 zbx_section_entry_t;
80
81 typedef enum
82 {
83 ZBX_SECTION_ENTRY_THE_ONLY,
84 ZBX_SECTION_ENTRY_PER_PROXY
85 }
86 zbx_entry_type_t;
87
88 typedef struct
89 {
90 const char *name;
91 zbx_entry_type_t entry_type;
92 zbx_user_type_t access_level;
93 int *res;
94 zbx_section_entry_t entries[ZBX_MAX_SECTION_ENTRIES];
95 }
96 zbx_status_section_t;
97
98 /******************************************************************************
99 * *
100 * Function: recv_agenthistory *
101 * *
102 * Purpose: processes the received values from active agents *
103 * *
104 ******************************************************************************/
recv_agenthistory(zbx_socket_t * sock,struct zbx_json_parse * jp,zbx_timespec_t * ts)105 static void recv_agenthistory(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts)
106 {
107 const char *__function_name = "recv_agenthistory";
108 char *info = NULL;
109 int ret;
110
111 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
112
113 if (SUCCEED != (ret = process_agent_history_data(sock, jp, ts, &info)))
114 {
115 zabbix_log(LOG_LEVEL_WARNING, "received invalid agent history data from \"%s\": %s", sock->peer, info);
116 }
117 else if (!ZBX_IS_RUNNING())
118 {
119 info = zbx_strdup(info, "Zabbix server shutdown in progress");
120 zabbix_log(LOG_LEVEL_WARNING, "cannot receive agent history data from \"%s\": %s", sock->peer, info);
121 ret = FAIL;
122 }
123
124 zbx_send_response(sock, ret, info, CONFIG_TIMEOUT);
125
126 zbx_free(info);
127
128 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
129 }
130
131 /******************************************************************************
132 * *
133 * Function: recv_senderhistory *
134 * *
135 * Purpose: processes the received values from senders *
136 * *
137 ******************************************************************************/
recv_senderhistory(zbx_socket_t * sock,struct zbx_json_parse * jp,zbx_timespec_t * ts)138 static void recv_senderhistory(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts)
139 {
140 const char *__function_name = "recv_senderhistory";
141 char *info = NULL;
142 int ret;
143
144 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
145
146 if (SUCCEED != (ret = process_sender_history_data(sock, jp, ts, &info)))
147 {
148 zabbix_log(LOG_LEVEL_WARNING, "received invalid sender data from \"%s\": %s", sock->peer, info);
149 }
150 else if (!ZBX_IS_RUNNING())
151 {
152 info = zbx_strdup(info, "Zabbix server shutdown in progress");
153 zabbix_log(LOG_LEVEL_WARNING, "cannot process sender data from \"%s\": %s", sock->peer, info);
154 ret = FAIL;
155 }
156
157 zbx_send_response(sock, ret, info, CONFIG_TIMEOUT);
158
159 zbx_free(info);
160
161 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
162 }
163
164 /******************************************************************************
165 * *
166 * Function: recv_proxyhistory *
167 * *
168 * Purpose: processes the received values from active proxies *
169 * *
170 ******************************************************************************/
recv_proxyhistory(zbx_socket_t * sock,struct zbx_json_parse * jp,zbx_timespec_t * ts)171 static void recv_proxyhistory(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts)
172 {
173 const char *__function_name = "recv_proxyhistory";
174 char *error = NULL;
175 int ret = FAIL;
176 DC_PROXY proxy;
177
178 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
179
180 if (SUCCEED != get_active_proxy_from_request(jp, &proxy, &error))
181 {
182 zabbix_log(LOG_LEVEL_WARNING, "cannot parse history data from active proxy at \"%s\": %s",
183 sock->peer, error);
184 goto out;
185 }
186
187 if (SUCCEED != zbx_proxy_check_permissions(&proxy, sock, &error))
188 {
189 zabbix_log(LOG_LEVEL_WARNING, "cannot accept connection from proxy \"%s\" at \"%s\", allowed address:"
190 " \"%s\": %s", proxy.host, sock->peer, proxy.proxy_address, error);
191 goto out;
192 }
193
194 zbx_update_proxy_data(&proxy, zbx_get_protocol_version(jp), time(NULL),
195 (0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0));
196
197 if (SUCCEED != zbx_check_protocol_version(&proxy))
198 {
199 goto out;
200 }
201
202 if (SUCCEED != (ret = process_proxy_history_data(&proxy, jp, ts, &error)))
203 {
204 zabbix_log(LOG_LEVEL_WARNING, "received invalid history data from proxy \"%s\" at \"%s\": %s",
205 proxy.host, sock->peer, error);
206 goto out;
207 }
208 out:
209 /* 'history data' request is sent only by pre 3.4 version proxies */
210 /* that did not have compression support */
211 zbx_send_response_ext(sock, ret, error, NULL, ZBX_TCP_PROTOCOL, CONFIG_TIMEOUT);
212
213 zbx_free(error);
214
215 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
216 }
217
218 /******************************************************************************
219 * *
220 * Function: send_proxyhistory *
221 * *
222 * Purpose: send history data to a Zabbix server *
223 * *
224 * Comments: 'history data' request is deprecated starting with Zabbix v3.4 *
225 * *
226 ******************************************************************************/
send_proxyhistory(zbx_socket_t * sock)227 static void send_proxyhistory(zbx_socket_t *sock)
228 {
229 const char *__function_name = "send_proxyhistory";
230
231 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
232
233 /* do not send any reply to server in this case as the server expects history data */
234 if (SUCCEED == check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "history data request"))
235 zbx_send_proxy_response(sock, FAIL, "Deprecated request", CONFIG_TIMEOUT);
236
237 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
238 }
239
240 /******************************************************************************
241 * *
242 * Function: recv_proxy_heartbeat *
243 * *
244 * Purpose: process heartbeat sent by proxy servers *
245 * *
246 * Return value: SUCCEED - processed successfully *
247 * FAIL - an error occurred *
248 * *
249 * Author: Alexander Vladishev *
250 * *
251 ******************************************************************************/
recv_proxy_heartbeat(zbx_socket_t * sock,struct zbx_json_parse * jp)252 static void recv_proxy_heartbeat(zbx_socket_t *sock, struct zbx_json_parse *jp)
253 {
254 const char *__function_name = "recv_proxy_heartbeat";
255
256 char *error = NULL;
257 int ret, flags = ZBX_TCP_PROTOCOL;
258 DC_PROXY proxy;
259
260 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
261
262 if (SUCCEED != (ret = get_active_proxy_from_request(jp, &proxy, &error)))
263 {
264 zabbix_log(LOG_LEVEL_WARNING, "cannot parse heartbeat from active proxy at \"%s\": %s",
265 sock->peer, error);
266 goto out;
267 }
268
269 if (SUCCEED != (ret = zbx_proxy_check_permissions(&proxy, sock, &error)))
270 {
271 zabbix_log(LOG_LEVEL_WARNING, "cannot accept connection from proxy \"%s\" at \"%s\", allowed address:"
272 " \"%s\": %s", proxy.host, sock->peer, proxy.proxy_address, error);
273 goto out;
274 }
275
276 zbx_update_proxy_data(&proxy, zbx_get_protocol_version(jp), time(NULL),
277 (0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0));
278
279 if (0 != proxy.auto_compress)
280 flags |= ZBX_TCP_COMPRESS;
281 out:
282 if (FAIL == ret && 0 != (sock->protocol & ZBX_TCP_COMPRESS))
283 flags |= ZBX_TCP_COMPRESS;
284
285 zbx_send_response_ext(sock, ret, error, NULL, flags, CONFIG_TIMEOUT);
286
287 zbx_free(error);
288
289 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
290 }
291
292 #define ZBX_GET_QUEUE_UNKNOWN -1
293 #define ZBX_GET_QUEUE_OVERVIEW 0
294 #define ZBX_GET_QUEUE_PROXY 1
295 #define ZBX_GET_QUEUE_DETAILS 2
296
297 /* queue stats split by delay times */
298 typedef struct
299 {
300 zbx_uint64_t id;
301 int delay5;
302 int delay10;
303 int delay30;
304 int delay60;
305 int delay300;
306 int delay600;
307 }
308 zbx_queue_stats_t;
309
310 /******************************************************************************
311 * *
312 * Function: queue_stats_update *
313 * *
314 * Purpose: update queue stats with a new item delay *
315 * *
316 * Parameters: stats - [IN] the queue stats *
317 * delay - [IN] the delay time of an delayed item *
318 * *
319 ******************************************************************************/
queue_stats_update(zbx_queue_stats_t * stats,int delay)320 static void queue_stats_update(zbx_queue_stats_t *stats, int delay)
321 {
322 if (10 >= delay)
323 stats->delay5++;
324 else if (30 >= delay)
325 stats->delay10++;
326 else if (60 >= delay)
327 stats->delay30++;
328 else if (300 >= delay)
329 stats->delay60++;
330 else if (600 >= delay)
331 stats->delay300++;
332 else
333 stats->delay600++;
334 }
335
336 /******************************************************************************
337 * *
338 * Function: queue_stats_export *
339 * *
340 * Purpose: export queue stats to JSON format *
341 * *
342 * Parameters: queue_stats - [IN] a hashset containing item stats *
343 * id_name - [IN] the name of stats id field *
344 * json - [OUT] the output JSON *
345 * *
346 ******************************************************************************/
queue_stats_export(zbx_hashset_t * queue_stats,const char * id_name,struct zbx_json * json)347 static void queue_stats_export(zbx_hashset_t *queue_stats, const char *id_name, struct zbx_json *json)
348 {
349 zbx_hashset_iter_t iter;
350 zbx_queue_stats_t *stats;
351
352 zbx_json_addarray(json, ZBX_PROTO_TAG_DATA);
353
354 zbx_hashset_iter_reset(queue_stats, &iter);
355
356 while (NULL != (stats = (zbx_queue_stats_t *)zbx_hashset_iter_next(&iter)))
357 {
358 zbx_json_addobject(json, NULL);
359 zbx_json_adduint64(json, id_name, stats->id);
360 zbx_json_adduint64(json, "delay5", stats->delay5);
361 zbx_json_adduint64(json, "delay10", stats->delay10);
362 zbx_json_adduint64(json, "delay30", stats->delay30);
363 zbx_json_adduint64(json, "delay60", stats->delay60);
364 zbx_json_adduint64(json, "delay300", stats->delay300);
365 zbx_json_adduint64(json, "delay600", stats->delay600);
366 zbx_json_close(json);
367 }
368
369 zbx_json_close(json);
370 }
371
372 /* queue item comparison function used to sort queue by nextcheck */
queue_compare_by_nextcheck_asc(zbx_queue_item_t ** d1,zbx_queue_item_t ** d2)373 static int queue_compare_by_nextcheck_asc(zbx_queue_item_t **d1, zbx_queue_item_t **d2)
374 {
375 zbx_queue_item_t *i1 = *d1, *i2 = *d2;
376
377 return i1->nextcheck - i2->nextcheck;
378 }
379
380 /******************************************************************************
381 * *
382 * Function: recv_getqueue *
383 * *
384 * Purpose: process queue request *
385 * *
386 * Parameters: sock - [IN] the request socket *
387 * jp - [IN] the request data *
388 * *
389 * Return value: SUCCEED - processed successfully *
390 * FAIL - an error occurred *
391 * *
392 ******************************************************************************/
recv_getqueue(zbx_socket_t * sock,struct zbx_json_parse * jp)393 static int recv_getqueue(zbx_socket_t *sock, struct zbx_json_parse *jp)
394 {
395 const char *__function_name = "recv_getqueue";
396 int ret = FAIL, request_type = ZBX_GET_QUEUE_UNKNOWN, now, i, limit;
397 char type[MAX_STRING_LEN], sessionid[MAX_STRING_LEN], limit_str[MAX_STRING_LEN];
398 zbx_user_t user;
399 zbx_vector_ptr_t queue;
400 struct zbx_json json;
401 zbx_hashset_t queue_stats;
402 zbx_queue_stats_t *stats;
403
404 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
405
406 if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_SID, sessionid, sizeof(sessionid), NULL) ||
407 SUCCEED != DBget_user_by_active_session(sessionid, &user) || USER_TYPE_SUPER_ADMIN > user.type)
408 {
409 zbx_send_response(sock, ret, "Permission denied.", CONFIG_TIMEOUT);
410 goto out;
411 }
412
413 if (FAIL != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_TYPE, type, sizeof(type), NULL))
414 {
415 if (0 == strcmp(type, ZBX_PROTO_VALUE_GET_QUEUE_OVERVIEW))
416 {
417 request_type = ZBX_GET_QUEUE_OVERVIEW;
418 }
419 else if (0 == strcmp(type, ZBX_PROTO_VALUE_GET_QUEUE_PROXY))
420 {
421 request_type = ZBX_GET_QUEUE_PROXY;
422 }
423 else if (0 == strcmp(type, ZBX_PROTO_VALUE_GET_QUEUE_DETAILS))
424 {
425 request_type = ZBX_GET_QUEUE_DETAILS;
426
427 if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_LIMIT, limit_str, sizeof(limit_str), NULL) ||
428 FAIL == is_uint31(limit_str, &limit))
429 {
430 zbx_send_response(sock, ret, "Unsupported limit value.", CONFIG_TIMEOUT);
431 goto out;
432 }
433 }
434 }
435
436 if (ZBX_GET_QUEUE_UNKNOWN == request_type)
437 {
438 zbx_send_response(sock, ret, "Unsupported request type.", CONFIG_TIMEOUT);
439 goto out;
440 }
441
442 now = time(NULL);
443 zbx_vector_ptr_create(&queue);
444 DCget_item_queue(&queue, ZBX_QUEUE_FROM_DEFAULT, ZBX_QUEUE_TO_INFINITY);
445
446 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
447
448 switch (request_type)
449 {
450 case ZBX_GET_QUEUE_OVERVIEW:
451 zbx_hashset_create(&queue_stats, 32, ZBX_DEFAULT_UINT64_HASH_FUNC,
452 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
453
454 /* gather queue stats by item type */
455 for (i = 0; i < queue.values_num; i++)
456 {
457 zbx_queue_item_t *item = (zbx_queue_item_t *)queue.values[i];
458 zbx_uint64_t id = item->type;
459
460 if (NULL == (stats = (zbx_queue_stats_t *)zbx_hashset_search(&queue_stats, &id)))
461 {
462 zbx_queue_stats_t data = {.id = id};
463
464 stats = (zbx_queue_stats_t *)zbx_hashset_insert(&queue_stats, &data, sizeof(data));
465 }
466 queue_stats_update(stats, now - item->nextcheck);
467 }
468
469 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS,
470 ZBX_JSON_TYPE_STRING);
471 queue_stats_export(&queue_stats, "itemtype", &json);
472 zbx_hashset_destroy(&queue_stats);
473
474 break;
475 case ZBX_GET_QUEUE_PROXY:
476 zbx_hashset_create(&queue_stats, 32, ZBX_DEFAULT_UINT64_HASH_FUNC,
477 ZBX_DEFAULT_UINT64_COMPARE_FUNC);
478
479 /* gather queue stats by proxy hostid */
480 for (i = 0; i < queue.values_num; i++)
481 {
482 zbx_queue_item_t *item = (zbx_queue_item_t *)queue.values[i];
483 zbx_uint64_t id = item->proxy_hostid;
484
485 if (NULL == (stats = (zbx_queue_stats_t *)zbx_hashset_search(&queue_stats, &id)))
486 {
487 zbx_queue_stats_t data = {.id = id};
488
489 stats = (zbx_queue_stats_t *)zbx_hashset_insert(&queue_stats, &data, sizeof(data));
490 }
491 queue_stats_update(stats, now - item->nextcheck);
492 }
493
494 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS,
495 ZBX_JSON_TYPE_STRING);
496 queue_stats_export(&queue_stats, "proxyid", &json);
497 zbx_hashset_destroy(&queue_stats);
498
499 break;
500 case ZBX_GET_QUEUE_DETAILS:
501 zbx_vector_ptr_sort(&queue, (zbx_compare_func_t)queue_compare_by_nextcheck_asc);
502 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS,
503 ZBX_JSON_TYPE_STRING);
504 zbx_json_addarray(&json, ZBX_PROTO_TAG_DATA);
505
506 for (i = 0; i < queue.values_num && i < limit; i++)
507 {
508 zbx_queue_item_t *item = (zbx_queue_item_t *)queue.values[i];
509
510 zbx_json_addobject(&json, NULL);
511 zbx_json_adduint64(&json, "itemid", item->itemid);
512 zbx_json_adduint64(&json, "nextcheck", item->nextcheck);
513 zbx_json_close(&json);
514 }
515
516 zbx_json_close(&json);
517 zbx_json_adduint64(&json, "total", queue.values_num);
518
519 break;
520 }
521
522 zabbix_log(LOG_LEVEL_DEBUG, "%s() json.buffer:'%s'", __function_name, json.buffer);
523
524 (void)zbx_tcp_send(sock, json.buffer);
525
526 DCfree_item_queue(&queue);
527 zbx_vector_ptr_destroy(&queue);
528
529 zbx_json_free(&json);
530
531 ret = SUCCEED;
532 out:
533 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
534
535 return ret;
536 }
537
DBget_template_count(zbx_uint64_t * count)538 static int DBget_template_count(zbx_uint64_t *count)
539 {
540 DB_RESULT result;
541 DB_ROW row;
542 int ret = FAIL;
543
544 if (NULL == (result = DBselect("select count(*) from hosts where status=%d", HOST_STATUS_TEMPLATE)))
545 goto out;
546
547 if (NULL == (row = DBfetch(result)) || SUCCEED != is_uint64(row[0], count))
548 goto out;
549
550 ret = SUCCEED;
551 out:
552 DBfree_result(result);
553
554 return ret;
555 }
556
DBget_user_count(zbx_uint64_t * count_online,zbx_uint64_t * count_offline)557 static int DBget_user_count(zbx_uint64_t *count_online, zbx_uint64_t *count_offline)
558 {
559 DB_RESULT result;
560 DB_ROW row;
561 zbx_uint64_t users_offline, users_online = 0;
562 int now, ret = FAIL;
563
564 if (NULL == (result = DBselect("select count(*) from users")))
565 goto out;
566
567 if (NULL == (row = DBfetch(result)) || SUCCEED != is_uint64(row[0], &users_offline))
568 goto out;
569
570 DBfree_result(result);
571 now = time(NULL);
572
573 if (NULL == (result = DBselect("select max(lastaccess) from sessions where status=%d group by userid,status",
574 ZBX_SESSION_ACTIVE)))
575 {
576 goto out;
577 }
578
579 while (NULL != (row = DBfetch(result)))
580 {
581 if (atoi(row[0]) + ZBX_USER_ONLINE_TIME < now)
582 continue;
583
584 users_online++;
585
586 if (0 == users_offline) /* new user can be created and log in between two selects */
587 continue;
588
589 users_offline--;
590 }
591
592 *count_online = users_online;
593 *count_offline = users_offline;
594 ret = SUCCEED;
595 out:
596 DBfree_result(result);
597
598 return ret;
599 }
600
601 /* auxiliary variables for status_stats_export() */
602
603 static zbx_entry_info_t templates, hosts_monitored, hosts_not_monitored, items_active_normal, items_active_notsupported,
604 items_disabled, triggers_enabled_ok, triggers_enabled_problem, triggers_disabled, users_online,
605 users_offline, required_performance;
606 static int templates_res, users_res;
607
zbx_status_counters_init(void)608 static void zbx_status_counters_init(void)
609 {
610 zbx_vector_ptr_create(&hosts_monitored.counters);
611 zbx_vector_ptr_create(&hosts_not_monitored.counters);
612 zbx_vector_ptr_create(&items_active_normal.counters);
613 zbx_vector_ptr_create(&items_active_notsupported.counters);
614 zbx_vector_ptr_create(&items_disabled.counters);
615 zbx_vector_ptr_create(&required_performance.counters);
616 }
617
zbx_status_counters_free(void)618 static void zbx_status_counters_free(void)
619 {
620 zbx_vector_ptr_clear_ext(&hosts_monitored.counters, zbx_default_mem_free_func);
621 zbx_vector_ptr_clear_ext(&hosts_not_monitored.counters, zbx_default_mem_free_func);
622 zbx_vector_ptr_clear_ext(&items_active_normal.counters, zbx_default_mem_free_func);
623 zbx_vector_ptr_clear_ext(&items_active_notsupported.counters, zbx_default_mem_free_func);
624 zbx_vector_ptr_clear_ext(&items_disabled.counters, zbx_default_mem_free_func);
625 zbx_vector_ptr_clear_ext(&required_performance.counters, zbx_default_mem_free_func);
626
627 zbx_vector_ptr_destroy(&hosts_monitored.counters);
628 zbx_vector_ptr_destroy(&hosts_not_monitored.counters);
629 zbx_vector_ptr_destroy(&items_active_normal.counters);
630 zbx_vector_ptr_destroy(&items_active_notsupported.counters);
631 zbx_vector_ptr_destroy(&items_disabled.counters);
632 zbx_vector_ptr_destroy(&required_performance.counters);
633 }
634
635 const zbx_status_section_t status_sections[] = {
636 /* {SECTION NAME, NUMBER OF SECTION ENTRIES SECTION ACCESS LEVEL SECTION READYNESS, */
637 /* { */
638 /* {ENTRY INFORMATION, COUNTER TYPE, */
639 /* { */
640 /* {ATTR. NAME, ATTRIBUTE VALUE}, */
641 /* ... (up to ZBX_MAX_ENTRY_ATTRIBUTES) */
642 /* } */
643 /* }, */
644 /* ... (up to ZBX_MAX_SECTION_ENTRIES) */
645 /* } */
646 /* }, */
647 /* ... */
648 {"template stats", ZBX_SECTION_ENTRY_THE_ONLY, USER_TYPE_ZABBIX_USER, &templates_res,
649 {
650 {&templates, ZBX_COUNTER_TYPE_UI64,
651 {
652 {NULL}
653 }
654 },
655 {NULL}
656 }
657 },
658 {"host stats", ZBX_SECTION_ENTRY_PER_PROXY, USER_TYPE_ZABBIX_USER, NULL,
659 {
660 {&hosts_monitored, ZBX_COUNTER_TYPE_UI64,
661 {
662 {"status", HOST_STATUS_MONITORED},
663 {NULL}
664 }
665 },
666 {&hosts_not_monitored, ZBX_COUNTER_TYPE_UI64,
667 {
668 {"status", HOST_STATUS_NOT_MONITORED},
669 {NULL}
670 }
671 },
672 {NULL}
673 }
674 },
675 {"item stats", ZBX_SECTION_ENTRY_PER_PROXY, USER_TYPE_ZABBIX_USER, NULL,
676 {
677 {&items_active_normal, ZBX_COUNTER_TYPE_UI64,
678 {
679 {"status", ITEM_STATUS_ACTIVE},
680 {"state", ITEM_STATE_NORMAL},
681 {NULL}
682 }
683 },
684 {&items_active_notsupported, ZBX_COUNTER_TYPE_UI64,
685 {
686 {"status", ITEM_STATUS_ACTIVE},
687 {"state", ITEM_STATE_NOTSUPPORTED},
688 {NULL}
689 }
690 },
691 {&items_disabled, ZBX_COUNTER_TYPE_UI64,
692 {
693 {"status", ITEM_STATUS_DISABLED},
694 {NULL}
695 }
696 },
697 {NULL}
698 }
699 },
700 {"trigger stats", ZBX_SECTION_ENTRY_THE_ONLY, USER_TYPE_ZABBIX_USER, NULL,
701 {
702 {&triggers_enabled_ok, ZBX_COUNTER_TYPE_UI64,
703 {
704 {"status", TRIGGER_STATUS_ENABLED},
705 {"value", TRIGGER_VALUE_OK},
706 {NULL}
707 }
708 },
709 {&triggers_enabled_problem, ZBX_COUNTER_TYPE_UI64,
710 {
711 {"status", TRIGGER_STATUS_ENABLED},
712 {"value", TRIGGER_VALUE_PROBLEM},
713 {NULL}
714 }
715 },
716 {&triggers_disabled, ZBX_COUNTER_TYPE_UI64,
717 {
718 {"status", TRIGGER_STATUS_DISABLED},
719 {NULL}
720 }
721 },
722 {NULL}
723 }
724 },
725 {"user stats", ZBX_SECTION_ENTRY_THE_ONLY, USER_TYPE_ZABBIX_USER, &users_res,
726 {
727 {&users_online, ZBX_COUNTER_TYPE_UI64,
728 {
729 {"status", ZBX_SESSION_ACTIVE},
730 {NULL}
731 }
732 },
733 {&users_offline, ZBX_COUNTER_TYPE_UI64,
734 {
735 {"status", ZBX_SESSION_PASSIVE},
736 {NULL}
737 }
738 },
739 {NULL}
740 }
741 },
742 {"required performance", ZBX_SECTION_ENTRY_PER_PROXY, USER_TYPE_SUPER_ADMIN, NULL,
743 {
744 {&required_performance, ZBX_COUNTER_TYPE_DBL,
745 {
746 {NULL}
747 }
748 },
749 {NULL}
750 }
751 },
752 {NULL}
753 };
754
status_entry_export(struct zbx_json * json,const zbx_section_entry_t * entry,zbx_counter_value_t counter_value,const zbx_uint64_t * proxyid)755 static void status_entry_export(struct zbx_json *json, const zbx_section_entry_t *entry,
756 zbx_counter_value_t counter_value, const zbx_uint64_t *proxyid)
757 {
758 const zbx_entry_attribute_t *attribute;
759 char *tmp = NULL;
760
761 zbx_json_addobject(json, NULL);
762
763 if (NULL != entry->attributes[0].name || NULL != proxyid)
764 {
765 zbx_json_addobject(json, "attributes");
766
767 if (NULL != proxyid)
768 zbx_json_adduint64(json, "proxyid", *proxyid);
769
770 for (attribute = entry->attributes; NULL != attribute->name; attribute++)
771 zbx_json_adduint64(json, attribute->name, attribute->value);
772
773 zbx_json_close(json);
774 }
775
776 switch (entry->counter_type)
777 {
778 case ZBX_COUNTER_TYPE_UI64:
779 zbx_json_adduint64(json, "count", counter_value.ui64);
780 break;
781 case ZBX_COUNTER_TYPE_DBL:
782 tmp = zbx_dsprintf(tmp, ZBX_FS_DBL, counter_value.dbl);
783 zbx_json_addstring(json, "count", tmp, ZBX_JSON_TYPE_STRING);
784 break;
785 default:
786 THIS_SHOULD_NEVER_HAPPEN;
787 }
788
789 zbx_json_close(json);
790
791 zbx_free(tmp);
792 }
793
status_stats_export(struct zbx_json * json,zbx_user_type_t access_level)794 static void status_stats_export(struct zbx_json *json, zbx_user_type_t access_level)
795 {
796 const zbx_status_section_t *section;
797 const zbx_section_entry_t *entry;
798 int i;
799
800 zbx_status_counters_init();
801
802 /* get status information */
803
804 templates_res = DBget_template_count(&templates.counter.ui64);
805 users_res = DBget_user_count(&users_online.counter.ui64, &users_offline.counter.ui64);
806 DCget_status(&hosts_monitored.counters, &hosts_not_monitored.counters, &items_active_normal.counters,
807 &items_active_notsupported.counters, &items_disabled.counters,
808 &triggers_enabled_ok.counter.ui64, &triggers_enabled_problem.counter.ui64,
809 &triggers_disabled.counter.ui64, &required_performance.counters);
810
811 /* add status information to JSON */
812 for (section = status_sections; NULL != section->name; section++)
813 {
814 if (access_level < section->access_level) /* skip sections user has no rights to access */
815 continue;
816
817 if (NULL != section->res && SUCCEED != *section->res) /* skip section we have no information for */
818 continue;
819
820 zbx_json_addarray(json, section->name);
821
822 for (entry = section->entries; NULL != entry->info; entry++)
823 {
824 switch (section->entry_type)
825 {
826 case ZBX_SECTION_ENTRY_THE_ONLY:
827 status_entry_export(json, entry, entry->info->counter, NULL);
828 break;
829 case ZBX_SECTION_ENTRY_PER_PROXY:
830 for (i = 0; i < entry->info->counters.values_num; i++)
831 {
832 const zbx_proxy_counter_t *proxy_counter;
833
834 proxy_counter = (zbx_proxy_counter_t *)entry->info->counters.values[i];
835 status_entry_export(json, entry, proxy_counter->counter_value,
836 &proxy_counter->proxyid);
837 }
838 break;
839 default:
840 THIS_SHOULD_NEVER_HAPPEN;
841 }
842 }
843
844 zbx_json_close(json);
845 }
846
847 zbx_status_counters_free();
848 }
849
850 /******************************************************************************
851 * *
852 * Function: recv_getstatus *
853 * *
854 * Purpose: process status request *
855 * *
856 * Parameters: sock - [IN] the request socket *
857 * jp - [IN] the request data *
858 * *
859 * Return value: SUCCEED - processed successfully *
860 * FAIL - an error occurred *
861 * *
862 ******************************************************************************/
recv_getstatus(zbx_socket_t * sock,struct zbx_json_parse * jp)863 static int recv_getstatus(zbx_socket_t *sock, struct zbx_json_parse *jp)
864 {
865 #define ZBX_GET_STATUS_UNKNOWN -1
866 #define ZBX_GET_STATUS_PING 0
867 #define ZBX_GET_STATUS_FULL 1
868
869 const char *__function_name = "recv_getstatus";
870 zbx_user_t user;
871 int ret = FAIL, request_type = ZBX_GET_STATUS_UNKNOWN;
872 char type[MAX_STRING_LEN], sessionid[MAX_STRING_LEN];
873 struct zbx_json json;
874
875 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
876
877 if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_SID, sessionid, sizeof(sessionid), NULL) ||
878 SUCCEED != DBget_user_by_active_session(sessionid, &user))
879 {
880 zbx_send_response(sock, ret, "Permission denied.", CONFIG_TIMEOUT);
881 goto out;
882 }
883
884 if (SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_TYPE, type, sizeof(type), NULL))
885 {
886 if (0 == strcmp(type, ZBX_PROTO_VALUE_GET_STATUS_PING))
887 {
888 request_type = ZBX_GET_STATUS_PING;
889 }
890 else if (0 == strcmp(type, ZBX_PROTO_VALUE_GET_STATUS_FULL))
891 {
892 request_type = ZBX_GET_STATUS_FULL;
893 }
894 }
895
896 if (ZBX_GET_STATUS_UNKNOWN == request_type)
897 {
898 zbx_send_response(sock, ret, "Unsupported request type.", CONFIG_TIMEOUT);
899 goto out;
900 }
901
902 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
903
904 switch (request_type)
905 {
906 case ZBX_GET_STATUS_PING:
907 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
908 zbx_json_addobject(&json, ZBX_PROTO_TAG_DATA);
909 zbx_json_close(&json);
910 break;
911 case ZBX_GET_STATUS_FULL:
912 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
913 zbx_json_addobject(&json, ZBX_PROTO_TAG_DATA);
914 status_stats_export(&json, user.type);
915 zbx_json_close(&json);
916 break;
917 default:
918 THIS_SHOULD_NEVER_HAPPEN;
919 }
920
921 zabbix_log(LOG_LEVEL_DEBUG, "%s() json.buffer:'%s'", __function_name, json.buffer);
922
923 (void)zbx_tcp_send(sock, json.buffer);
924
925 zbx_json_free(&json);
926
927 ret = SUCCEED;
928 out:
929 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
930
931 return ret;
932
933 #undef ZBX_GET_STATUS_UNKNOWN
934 #undef ZBX_GET_STATUS_PING
935 #undef ZBX_GET_STATUS_FULL
936 }
937
938 /******************************************************************************
939 * *
940 * Function: send_internal_stats_json *
941 * *
942 * Purpose: process Zabbix stats request *
943 * *
944 * Parameters: sock - [IN] the request socket *
945 * jp - [IN] the request data *
946 * *
947 * Return value: SUCCEED - processed successfully *
948 * FAIL - an error occurred *
949 * *
950 ******************************************************************************/
send_internal_stats_json(zbx_socket_t * sock,const struct zbx_json_parse * jp)951 static int send_internal_stats_json(zbx_socket_t *sock, const struct zbx_json_parse *jp)
952 {
953 const char *__function_name = "send_internal_stats_json";
954 struct zbx_json json;
955 char type[MAX_STRING_LEN], error[MAX_STRING_LEN];
956 int ret = FAIL;
957
958 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
959
960 if (NULL == CONFIG_STATS_ALLOWED_IP ||
961 SUCCEED != zbx_tcp_check_allowed_peers(sock, CONFIG_STATS_ALLOWED_IP))
962 {
963 zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming stats request: %s",
964 NULL == CONFIG_STATS_ALLOWED_IP ? "StatsAllowedIP not set" : zbx_socket_strerror());
965 strscpy(error, "Permission denied.");
966 goto out;
967 }
968
969 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
970
971 if (SUCCEED == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_TYPE, type, sizeof(type), NULL) &&
972 0 == strcmp(type, ZBX_PROTO_VALUE_ZABBIX_STATS_QUEUE))
973 {
974 char from_str[ZBX_MAX_UINT64_LEN + 1], to_str[ZBX_MAX_UINT64_LEN + 1];
975 int from = ZBX_QUEUE_FROM_DEFAULT, to = ZBX_QUEUE_TO_INFINITY;
976 struct zbx_json_parse jp_data;
977
978 if (SUCCEED != zbx_json_brackets_by_name(jp, ZBX_PROTO_TAG_PARAMS, &jp_data))
979 {
980 zbx_snprintf(error, sizeof(error), "cannot find tag: %s", ZBX_PROTO_TAG_PARAMS);
981 goto param_error;
982 }
983
984 if (SUCCEED == zbx_json_value_by_name(&jp_data, ZBX_PROTO_TAG_FROM, from_str, sizeof(from_str), NULL)
985 && FAIL == is_time_suffix(from_str, &from, ZBX_LENGTH_UNLIMITED))
986 {
987 strscpy(error, "invalid 'from' parameter");
988 goto param_error;
989 }
990
991 if (SUCCEED == zbx_json_value_by_name(&jp_data, ZBX_PROTO_TAG_TO, to_str, sizeof(to_str), NULL) &&
992 FAIL == is_time_suffix(to_str, &to, ZBX_LENGTH_UNLIMITED))
993 {
994 strscpy(error, "invalid 'to' parameter");
995 goto param_error;
996 }
997
998 if (ZBX_QUEUE_TO_INFINITY != to && from > to)
999 {
1000 strscpy(error, "parameters represent an invalid interval");
1001 goto param_error;
1002 }
1003
1004 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
1005 zbx_json_adduint64(&json, ZBX_PROTO_VALUE_ZABBIX_STATS_QUEUE, DCget_item_queue(NULL, from, to));
1006 }
1007 else
1008 {
1009 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
1010 zbx_json_addobject(&json, ZBX_PROTO_TAG_DATA);
1011
1012 zbx_get_zabbix_stats(&json);
1013
1014 zbx_json_close(&json);
1015 }
1016
1017 (void)zbx_tcp_send(sock, json.buffer);
1018 ret = SUCCEED;
1019 param_error:
1020 zbx_json_free(&json);
1021 out:
1022 if (SUCCEED != ret)
1023 zbx_send_response(sock, ret, error, CONFIG_TIMEOUT);
1024
1025 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1026
1027 return ret;
1028 }
1029
active_passive_misconfig(zbx_socket_t * sock)1030 static void active_passive_misconfig(zbx_socket_t *sock)
1031 {
1032 char *msg = NULL;
1033
1034 msg = zbx_dsprintf(msg, "misconfiguration error: the proxy is running in the active mode but server at \"%s\""
1035 " sends requests to it as to proxy in passive mode", sock->peer);
1036
1037 zabbix_log(LOG_LEVEL_WARNING, "%s", msg);
1038 zbx_send_proxy_response(sock, FAIL, msg, CONFIG_TIMEOUT);
1039 zbx_free(msg);
1040 }
1041
process_trap(zbx_socket_t * sock,char * s,zbx_timespec_t * ts)1042 static int process_trap(zbx_socket_t *sock, char *s, zbx_timespec_t *ts)
1043 {
1044 int ret = SUCCEED;
1045
1046 zbx_rtrim(s, " \r\n");
1047
1048 zabbix_log(LOG_LEVEL_DEBUG, "trapper got '%s'", s);
1049
1050 if ('{' == *s) /* JSON protocol */
1051 {
1052 struct zbx_json_parse jp;
1053 char value[MAX_STRING_LEN];
1054
1055 if (SUCCEED != zbx_json_open(s, &jp))
1056 {
1057 zbx_send_response(sock, FAIL, zbx_json_strerror(), CONFIG_TIMEOUT);
1058 zabbix_log(LOG_LEVEL_WARNING, "received invalid JSON object from %s: %s",
1059 sock->peer, zbx_json_strerror());
1060 return FAIL;
1061 }
1062
1063 if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_REQUEST, value, sizeof(value), NULL))
1064 {
1065 if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG))
1066 {
1067 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1068 {
1069 send_proxyconfig(sock, &jp);
1070 }
1071 else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
1072 {
1073 zabbix_log(LOG_LEVEL_WARNING, "received configuration data from server"
1074 " at \"%s\", datalen " ZBX_FS_SIZE_T,
1075 sock->peer, (zbx_fs_size_t)(jp.end - jp.start + 1));
1076 recv_proxyconfig(sock, &jp);
1077 }
1078 else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_ACTIVE))
1079 {
1080 /* This is a misconfiguration: the proxy is configured in active mode */
1081 /* but server sends requests to it as to a proxy in passive mode. To */
1082 /* prevent logging of this problem for every request we report it */
1083 /* only when the server sends configuration to the proxy and ignore */
1084 /* it for other requests. */
1085 active_passive_misconfig(sock);
1086 }
1087 }
1088 else if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA))
1089 {
1090 recv_agenthistory(sock, &jp, ts);
1091 }
1092 else if (0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA))
1093 {
1094 recv_senderhistory(sock, &jp, ts);
1095 }
1096 else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_TASKS))
1097 {
1098 if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
1099 zbx_send_task_data(sock, ts);
1100 }
1101 else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_DATA))
1102 {
1103 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1104 zbx_recv_proxy_data(sock, &jp, ts);
1105 else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
1106 zbx_send_proxy_data(sock, ts);
1107 }
1108 else if (0 == strcmp(value, ZBX_PROTO_VALUE_HISTORY_DATA))
1109 {
1110 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1111 recv_proxyhistory(sock, &jp, ts);
1112 else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
1113 send_proxyhistory(sock);
1114 }
1115 else if (0 == strcmp(value, ZBX_PROTO_VALUE_DISCOVERY_DATA))
1116 {
1117 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1118 recv_discovery_data(sock, &jp, ts);
1119 else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
1120 send_discovery_data(sock);
1121 }
1122 else if (0 == strcmp(value, ZBX_PROTO_VALUE_AUTO_REGISTRATION_DATA))
1123 {
1124 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1125 recv_areg_data(sock, &jp, ts);
1126 else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
1127 send_areg_data(sock);
1128 }
1129 else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT))
1130 {
1131 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1132 recv_proxy_heartbeat(sock, &jp);
1133 }
1134 else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS))
1135 {
1136 ret = send_list_of_active_checks_json(sock, &jp);
1137 }
1138 else if (0 == strcmp(value, ZBX_PROTO_VALUE_HOST_AVAILABILITY))
1139 {
1140 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1141 recv_host_availability(sock, &jp);
1142 else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
1143 send_host_availability(sock);
1144 }
1145 else if (0 == strcmp(value, ZBX_PROTO_VALUE_COMMAND))
1146 {
1147 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1148 ret = node_process_command(sock, s, &jp);
1149 }
1150 else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_QUEUE))
1151 {
1152 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1153 ret = recv_getqueue(sock, &jp);
1154 }
1155 else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_STATUS))
1156 {
1157 if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
1158 ret = recv_getstatus(sock, &jp);
1159 }
1160 else if (0 == strcmp(value, ZBX_PROTO_VALUE_ZABBIX_STATS))
1161 {
1162 ret = send_internal_stats_json(sock, &jp);
1163 }
1164 else
1165 zabbix_log(LOG_LEVEL_WARNING, "unknown request received [%s]", value);
1166 }
1167 }
1168 else if (0 == strncmp(s, "ZBX_GET_ACTIVE_CHECKS", 21)) /* request for list of active checks */
1169 {
1170 ret = send_list_of_active_checks(sock, s);
1171 }
1172 else
1173 {
1174 char value_dec[MAX_BUFFER_LEN], lastlogsize[ZBX_MAX_UINT64_LEN], timestamp[11],
1175 source[HISTORY_LOG_SOURCE_LEN_MAX], severity[11],
1176 host[HOST_HOST_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1],
1177 key[ITEM_KEY_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1];
1178 zbx_agent_value_t av;
1179 zbx_host_key_t hk = {host, key};
1180 DC_ITEM item;
1181 int errcode;
1182
1183 memset(&av, 0, sizeof(zbx_agent_value_t));
1184
1185 if ('<' == *s) /* XML protocol */
1186 {
1187 comms_parse_response(s, host, sizeof(host), key, sizeof(key), value_dec,
1188 sizeof(value_dec), lastlogsize, sizeof(lastlogsize), timestamp,
1189 sizeof(timestamp), source, sizeof(source), severity, sizeof(severity));
1190
1191 av.value = value_dec;
1192 if (SUCCEED != is_uint64(lastlogsize, &av.lastlogsize))
1193 av.lastlogsize = 0;
1194 av.timestamp = atoi(timestamp);
1195 av.source = source;
1196 av.severity = atoi(severity);
1197 }
1198 else
1199 {
1200 char *pl, *pr;
1201
1202 pl = s;
1203 if (NULL == (pr = strchr(pl, ':')))
1204 return FAIL;
1205
1206 *pr = '\0';
1207 zbx_strlcpy(host, pl, sizeof(host));
1208 *pr = ':';
1209
1210 pl = pr + 1;
1211 if (NULL == (pr = strchr(pl, ':')))
1212 return FAIL;
1213
1214 *pr = '\0';
1215 zbx_strlcpy(key, pl, sizeof(key));
1216 *pr = ':';
1217
1218 av.value = pr + 1;
1219 av.severity = 0;
1220 }
1221
1222 zbx_timespec(&av.ts);
1223
1224 if (0 == strcmp(av.value, ZBX_NOTSUPPORTED))
1225 av.state = ITEM_STATE_NOTSUPPORTED;
1226
1227 DCconfig_get_items_by_keys(&item, &hk, &errcode, 1);
1228 process_history_data(&item, &av, &errcode, 1);
1229 DCconfig_clean_items(&item, &errcode, 1);
1230
1231 zbx_alarm_on(CONFIG_TIMEOUT);
1232 if (SUCCEED != zbx_tcp_send_raw(sock, "OK"))
1233 zabbix_log(LOG_LEVEL_WARNING, "Error sending result back");
1234 zbx_alarm_off();
1235 }
1236
1237 return ret;
1238 }
1239
process_trapper_child(zbx_socket_t * sock,zbx_timespec_t * ts)1240 static void process_trapper_child(zbx_socket_t *sock, zbx_timespec_t *ts)
1241 {
1242 if (SUCCEED != zbx_tcp_recv_to(sock, CONFIG_TRAPPER_TIMEOUT))
1243 return;
1244
1245 process_trap(sock, sock->buffer, ts);
1246 }
1247
ZBX_THREAD_ENTRY(trapper_thread,args)1248 ZBX_THREAD_ENTRY(trapper_thread, args)
1249 {
1250 double sec = 0.0;
1251 zbx_socket_t s;
1252 int ret;
1253
1254 process_type = ((zbx_thread_args_t *)args)->process_type;
1255 server_num = ((zbx_thread_args_t *)args)->server_num;
1256 process_num = ((zbx_thread_args_t *)args)->process_num;
1257
1258 zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
1259 server_num, get_process_type_string(process_type), process_num);
1260
1261 update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
1262
1263 memcpy(&s, (zbx_socket_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_socket_t));
1264
1265 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1266 zbx_tls_init_child();
1267 find_psk_in_cache = DCget_psk_by_identity;
1268 #endif
1269 zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num);
1270
1271 DBconnect(ZBX_DB_CONNECT_NORMAL);
1272
1273 /* configuration sync is performed by trappers on passive Zabbix proxy */
1274 if (1 == process_num && 0 == CONFIG_CONFSYNCER_FORKS)
1275 {
1276 zbx_setproctitle("%s [syncing configuration]", get_process_type_string(process_type));
1277 DCsync_configuration(ZBX_DBSYNC_INIT);
1278 }
1279
1280 while (ZBX_IS_RUNNING())
1281 {
1282 zbx_setproctitle("%s #%d [processed data in " ZBX_FS_DBL " sec, waiting for connection]",
1283 get_process_type_string(process_type), process_num, sec);
1284
1285 update_selfmon_counter(ZBX_PROCESS_STATE_IDLE);
1286
1287 /* Trapper has to accept all types of connections it can accept with the specified configuration. */
1288 /* Only after receiving data it is known who has sent them and one can decide to accept or discard */
1289 /* the data. */
1290 ret = zbx_tcp_accept(&s, ZBX_TCP_SEC_TLS_CERT | ZBX_TCP_SEC_TLS_PSK | ZBX_TCP_SEC_UNENCRYPTED);
1291 zbx_update_env(zbx_time());
1292
1293 if (SUCCEED == ret)
1294 {
1295 zbx_timespec_t ts;
1296
1297 /* get connection timestamp */
1298 zbx_timespec(&ts);
1299
1300 update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
1301
1302 zbx_setproctitle("%s #%d [processing data]", get_process_type_string(process_type),
1303 process_num);
1304
1305 sec = zbx_time();
1306 process_trapper_child(&s, &ts);
1307 sec = zbx_time() - sec;
1308
1309 zbx_tcp_unaccept(&s);
1310 }
1311 else if (EINTR != zbx_socket_last_error())
1312 {
1313 zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s",
1314 zbx_socket_strerror());
1315 }
1316 }
1317
1318 zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num);
1319
1320 while (1)
1321 zbx_sleep(SEC_PER_MIN);
1322 }
1323