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