1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "listener.h"
22
23 #include "comms.h"
24 #include "cfg.h"
25 #include "zbxconf.h"
26 #include "stats.h"
27 #include "sysinfo.h"
28 #include "log.h"
29
30 extern unsigned char program_type;
31 extern ZBX_THREAD_LOCAL unsigned char process_type;
32 extern ZBX_THREAD_LOCAL int server_num, process_num;
33
34 #if defined(ZABBIX_SERVICE)
35 # include "service.h"
36 #elif defined(ZABBIX_DAEMON)
37 # include "daemon.h"
38 #endif
39
40 #include "zbxcrypto.h"
41 #include "../libs/zbxcrypto/tls_tcp_active.h"
42
process_listener(zbx_socket_t * s)43 static void process_listener(zbx_socket_t *s)
44 {
45 AGENT_RESULT result;
46 char **value = NULL;
47 int ret;
48
49 if (SUCCEED == (ret = zbx_tcp_recv_to(s, CONFIG_TIMEOUT)))
50 {
51 zbx_rtrim(s->buffer, "\r\n");
52
53 zabbix_log(LOG_LEVEL_DEBUG, "Requested [%s]", s->buffer);
54
55 init_result(&result);
56
57 if (SUCCEED == process(s->buffer, PROCESS_WITH_ALIAS, &result))
58 {
59 if (NULL != (value = GET_TEXT_RESULT(&result)))
60 {
61 zabbix_log(LOG_LEVEL_DEBUG, "Sending back [%s]", *value);
62 ret = zbx_tcp_send_to(s, *value, CONFIG_TIMEOUT);
63 }
64 }
65 else
66 {
67 value = GET_MSG_RESULT(&result);
68
69 if (NULL != value)
70 {
71 static char *buffer = NULL;
72 static size_t buffer_alloc = 256;
73 size_t buffer_offset = 0;
74
75 zabbix_log(LOG_LEVEL_DEBUG, "Sending back [" ZBX_NOTSUPPORTED ": %s]", *value);
76
77 if (NULL == buffer)
78 buffer = (char *)zbx_malloc(buffer, buffer_alloc);
79
80 zbx_strncpy_alloc(&buffer, &buffer_alloc, &buffer_offset,
81 ZBX_NOTSUPPORTED, ZBX_CONST_STRLEN(ZBX_NOTSUPPORTED));
82 buffer_offset++;
83 zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, *value);
84
85 ret = zbx_tcp_send_bytes_to(s, buffer, buffer_offset, CONFIG_TIMEOUT);
86 }
87 else
88 {
89 zabbix_log(LOG_LEVEL_DEBUG, "Sending back [" ZBX_NOTSUPPORTED "]");
90
91 ret = zbx_tcp_send_to(s, ZBX_NOTSUPPORTED, CONFIG_TIMEOUT);
92 }
93 }
94
95 free_result(&result);
96 }
97
98 if (FAIL == ret)
99 zabbix_log(LOG_LEVEL_DEBUG, "Process listener error: %s", zbx_socket_strerror());
100 }
101
ZBX_THREAD_ENTRY(listener_thread,args)102 ZBX_THREAD_ENTRY(listener_thread, args)
103 {
104 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
105 char *msg = NULL;
106 #endif
107 int ret;
108 zbx_socket_t s;
109
110 assert(args);
111 assert(((zbx_thread_args_t *)args)->args);
112
113 process_type = ((zbx_thread_args_t *)args)->process_type;
114 server_num = ((zbx_thread_args_t *)args)->server_num;
115 process_num = ((zbx_thread_args_t *)args)->process_num;
116
117 zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
118 server_num, get_process_type_string(process_type), process_num);
119
120 memcpy(&s, (zbx_socket_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_socket_t));
121
122 zbx_free(args);
123
124 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
125 zbx_tls_init_child();
126 #endif
127 while (ZBX_IS_RUNNING())
128 {
129 zbx_setproctitle("listener #%d [waiting for connection]", process_num);
130 ret = zbx_tcp_accept(&s, configured_tls_accept_modes);
131 zbx_update_env(zbx_time());
132
133 if (SUCCEED == ret)
134 {
135 zbx_setproctitle("listener #%d [processing request]", process_num);
136
137 if ('\0' != *CONFIG_HOSTS_ALLOWED &&
138 SUCCEED == (ret = zbx_tcp_check_allowed_peers(&s, CONFIG_HOSTS_ALLOWED)))
139 {
140 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
141 if (ZBX_TCP_SEC_TLS_CERT != s.connection_type ||
142 SUCCEED == (ret = zbx_check_server_issuer_subject(&s, &msg)))
143 #endif
144 {
145 process_listener(&s);
146 }
147 }
148
149 zbx_tcp_unaccept(&s);
150 }
151
152 if (SUCCEED == ret || EINTR == zbx_socket_last_error())
153 continue;
154
155 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
156 if (NULL != msg)
157 {
158 zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", msg);
159 zbx_free(msg);
160 }
161 else
162 #endif
163 {
164 zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s",
165 zbx_socket_strerror());
166 }
167
168 if (ZBX_IS_RUNNING())
169 zbx_sleep(1);
170 }
171
172 #ifdef _WINDOWS
173 ZBX_DO_EXIT();
174
175 zbx_thread_exit(EXIT_SUCCESS);
176 #else
177 zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num);
178
179 while (1)
180 zbx_sleep(SEC_PER_MIN);
181 #endif
182 }
183