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