1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "db.h"
22 #include "log.h"
23 #include "proxy.h"
24
25 #include "proxydata.h"
26 #include "../../libs/zbxcrypto/tls_tcp_active.h"
27 #include "zbxtasks.h"
28 #include "mutexs.h"
29 #include "daemon.h"
30 #include "zbxcompress.h"
31
32 extern unsigned char program_type;
33 static zbx_mutex_t proxy_lock = ZBX_MUTEX_NULL;
34
35 #define LOCK_PROXY_HISTORY if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) zbx_mutex_lock(proxy_lock)
36 #define UNLOCK_PROXY_HISTORY if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) zbx_mutex_unlock(proxy_lock)
37
zbx_send_proxy_data_response(const DC_PROXY * proxy,zbx_socket_t * sock,const char * info,int upload_status)38 int zbx_send_proxy_data_response(const DC_PROXY *proxy, zbx_socket_t *sock, const char *info, int upload_status)
39 {
40 struct zbx_json json;
41 zbx_vector_ptr_t tasks;
42 int ret, flags = ZBX_TCP_PROTOCOL, status;
43
44 zbx_vector_ptr_create(&tasks);
45
46 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
47
48 switch (upload_status)
49 {
50 case ZBX_PROXY_UPLOAD_DISABLED:
51 zbx_json_addstring(&json, ZBX_PROTO_TAG_PROXY_UPLOAD, ZBX_PROTO_VALUE_PROXY_UPLOAD_DISABLED,
52 ZBX_JSON_TYPE_STRING);
53 status = FAIL;
54 break;
55 case ZBX_PROXY_UPLOAD_ENABLED:
56 zbx_json_addstring(&json, ZBX_PROTO_TAG_PROXY_UPLOAD, ZBX_PROTO_VALUE_PROXY_UPLOAD_ENABLED,
57 ZBX_JSON_TYPE_STRING);
58 ZBX_FALLTHROUGH;
59 default:
60 status = SUCCEED;
61 }
62
63 if (SUCCEED == status)
64 {
65 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
66 zbx_tm_get_remote_tasks(&tasks, proxy->hostid);
67 }
68 else
69 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING);
70
71 if (NULL != info && '\0' != *info)
72 zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, info, ZBX_JSON_TYPE_STRING);
73
74 if (0 != tasks.values_num)
75 zbx_tm_json_serialize_tasks(&json, &tasks);
76
77 if (0 != proxy->auto_compress)
78 flags |= ZBX_TCP_COMPRESS;
79
80 if (SUCCEED == (ret = zbx_tcp_send_ext(sock, json.buffer, strlen(json.buffer), 0, flags, 0)))
81 {
82 if (0 != tasks.values_num)
83 zbx_tm_update_task_status(&tasks, ZBX_TM_STATUS_INPROGRESS);
84 }
85
86 zbx_json_free(&json);
87
88 zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
89 zbx_vector_ptr_destroy(&tasks);
90
91 return ret;
92 }
93
94 /******************************************************************************
95 * *
96 * Function: zbx_recv_proxy_data *
97 * *
98 * Purpose: receive 'proxy data' request from proxy *
99 * *
100 * Parameters: sock - [IN] the connection socket *
101 * jp - [IN] the received JSON data *
102 * ts - [IN] the connection timestamp *
103 * *
104 ******************************************************************************/
zbx_recv_proxy_data(zbx_socket_t * sock,struct zbx_json_parse * jp,zbx_timespec_t * ts)105 void zbx_recv_proxy_data(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts)
106 {
107 int ret = FAIL, upload_status = 0, status, version, responded = 0;
108 char *error = NULL;
109 DC_PROXY proxy;
110
111 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
112
113 if (SUCCEED != (status = get_active_proxy_from_request(jp, &proxy, &error)))
114 {
115 zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy data from active proxy at \"%s\": %s",
116 sock->peer, error);
117 goto out;
118 }
119
120 if (SUCCEED != (status = zbx_proxy_check_permissions(&proxy, sock, &error)))
121 {
122 zabbix_log(LOG_LEVEL_WARNING, "cannot accept connection from proxy \"%s\" at \"%s\", allowed address:"
123 " \"%s\": %s", proxy.host, sock->peer, proxy.proxy_address, error);
124 goto out;
125 }
126
127 version = zbx_get_proxy_protocol_version(jp);
128
129 if (SUCCEED != zbx_check_protocol_version(&proxy, version))
130 {
131 goto out;
132 }
133
134 if (FAIL == (ret = zbx_hc_check_proxy(proxy.hostid)))
135 {
136 upload_status = ZBX_PROXY_UPLOAD_DISABLED;
137 }
138 else
139 {
140 upload_status = ZBX_PROXY_UPLOAD_ENABLED;
141
142 if (SUCCEED != (ret = process_proxy_data(&proxy, jp, ts, HOST_STATUS_PROXY_ACTIVE, NULL, &error)))
143 {
144 zabbix_log(LOG_LEVEL_WARNING, "received invalid proxy data from proxy \"%s\" at \"%s\": %s",
145 proxy.host, sock->peer, error);
146 goto out;
147 }
148 }
149
150 if (!ZBX_IS_RUNNING())
151 {
152 error = zbx_strdup(error, "Zabbix server shutdown in progress");
153 zabbix_log(LOG_LEVEL_WARNING, "cannot process proxy data from active proxy at \"%s\": %s",
154 sock->peer, error);
155 ret = FAIL;
156 goto out;
157 }
158
159 zbx_send_proxy_data_response(&proxy, sock, error, upload_status);
160 responded = 1;
161
162 out:
163 if (SUCCEED == status) /* moved the unpredictable long operation to the end */
164 /* we are trying to save info about lastaccess to detect communication problem */
165 {
166 zbx_update_proxy_data(&proxy, version, ts->sec,
167 (0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0), 0);
168 }
169
170 if (0 == responded)
171 {
172 int flags = ZBX_TCP_PROTOCOL;
173
174 if (0 != (sock->protocol & ZBX_TCP_COMPRESS))
175 flags |= ZBX_TCP_COMPRESS;
176
177 zbx_send_response_ext(sock, ret, error, NULL, flags, CONFIG_TIMEOUT);
178 }
179
180 zbx_free(error);
181
182 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
183 }
184
185 /******************************************************************************
186 * *
187 * Function: send_data_to_server *
188 * *
189 * Purpose: sends data from proxy to server *
190 * *
191 * Parameters: sock - [IN] the connection socket *
192 * data - [IN] the data to send *
193 * error - [OUT] the error message *
194 * *
195 ******************************************************************************/
send_data_to_server(zbx_socket_t * sock,char ** buffer,size_t buffer_size,size_t reserved,char ** error)196 static int send_data_to_server(zbx_socket_t *sock, char **buffer, size_t buffer_size, size_t reserved,
197 char **error)
198 {
199 if (SUCCEED != zbx_tcp_send_ext(sock, *buffer, buffer_size, reserved, ZBX_TCP_PROTOCOL | ZBX_TCP_COMPRESS,
200 CONFIG_TIMEOUT))
201 {
202 *error = zbx_strdup(*error, zbx_socket_strerror());
203 return FAIL;
204 }
205
206 zbx_free(*buffer);
207
208 if (SUCCEED != zbx_recv_response(sock, CONFIG_TIMEOUT, error))
209 return FAIL;
210
211 return SUCCEED;
212 }
213
214 /******************************************************************************
215 * *
216 * Function: zbx_send_proxy_data *
217 * *
218 * Purpose: sends 'proxy data' request to server *
219 * *
220 * Parameters: sock - [IN] the connection socket *
221 * ts - [IN] the connection timestamp *
222 * *
223 ******************************************************************************/
zbx_send_proxy_data(zbx_socket_t * sock,zbx_timespec_t * ts)224 void zbx_send_proxy_data(zbx_socket_t *sock, zbx_timespec_t *ts)
225 {
226 struct zbx_json j;
227 zbx_uint64_t areg_lastid = 0, history_lastid = 0, discovery_lastid = 0;
228 char *error = NULL, *buffer = NULL;
229 int availability_ts, more_history, more_discovery, more_areg, proxy_delay;
230 zbx_vector_ptr_t tasks;
231 struct zbx_json_parse jp, jp_tasks;
232 size_t buffer_size, reserved;
233
234 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
235
236 if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "proxy data request"))
237 {
238 /* do not send any reply to server in this case as the server expects proxy data */
239 goto out;
240 }
241
242 LOCK_PROXY_HISTORY;
243 zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
244
245 zbx_json_addstring(&j, ZBX_PROTO_TAG_SESSION, zbx_dc_get_session_token(), ZBX_JSON_TYPE_STRING);
246 get_host_availability_data(&j, &availability_ts);
247 proxy_get_hist_data(&j, &history_lastid, &more_history);
248 proxy_get_dhis_data(&j, &discovery_lastid, &more_discovery);
249 proxy_get_areg_data(&j, &areg_lastid, &more_areg);
250
251 zbx_vector_ptr_create(&tasks);
252 zbx_tm_get_remote_tasks(&tasks, 0);
253
254 if (0 != tasks.values_num)
255 zbx_tm_json_serialize_tasks(&j, &tasks);
256
257 if (ZBX_PROXY_DATA_MORE == more_history || ZBX_PROXY_DATA_MORE == more_discovery ||
258 ZBX_PROXY_DATA_MORE == more_areg)
259 {
260 zbx_json_adduint64(&j, ZBX_PROTO_TAG_MORE, ZBX_PROXY_DATA_MORE);
261 }
262
263 zbx_json_addstring(&j, ZBX_PROTO_TAG_VERSION, ZABBIX_VERSION, ZBX_JSON_TYPE_STRING);
264 zbx_json_adduint64(&j, ZBX_PROTO_TAG_CLOCK, ts->sec);
265 zbx_json_adduint64(&j, ZBX_PROTO_TAG_NS, ts->ns);
266
267 if (0 != history_lastid && 0 != (proxy_delay = proxy_get_delay(history_lastid)))
268 zbx_json_adduint64(&j, ZBX_PROTO_TAG_PROXY_DELAY, proxy_delay);
269
270 if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size))
271 {
272 zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror());
273 goto clean;
274 }
275
276 reserved = j.buffer_size;
277 zbx_json_free(&j); /* json buffer can be large, free as fast as possible */
278
279 if (SUCCEED == send_data_to_server(sock, &buffer, buffer_size, reserved, &error))
280 {
281 zbx_set_availability_diff_ts(availability_ts);
282
283 DBbegin();
284
285 if (0 != history_lastid)
286 proxy_set_hist_lastid(history_lastid);
287
288 if (0 != discovery_lastid)
289 proxy_set_dhis_lastid(discovery_lastid);
290
291 if (0 != areg_lastid)
292 proxy_set_areg_lastid(areg_lastid);
293
294 if (0 != tasks.values_num)
295 {
296 zbx_tm_update_task_status(&tasks, ZBX_TM_STATUS_DONE);
297 zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
298 }
299
300 if (SUCCEED == zbx_json_open(sock->buffer, &jp))
301 {
302 if (SUCCEED == zbx_json_brackets_by_name(&jp, ZBX_PROTO_TAG_TASKS, &jp_tasks))
303 {
304 zbx_tm_json_deserialize_tasks(&jp_tasks, &tasks);
305 zbx_tm_save_tasks(&tasks);
306 }
307 }
308
309 DBcommit();
310 }
311 else
312 {
313 zabbix_log(LOG_LEVEL_WARNING, "cannot send proxy data to server at \"%s\": %s", sock->peer, error);
314 zbx_free(error);
315 }
316 clean:
317 zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
318 zbx_vector_ptr_destroy(&tasks);
319
320 zbx_json_free(&j);
321 UNLOCK_PROXY_HISTORY;
322 out:
323 zbx_free(buffer);
324 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
325 }
326
327
328 /******************************************************************************
329 * *
330 * Function: zbx_send_task_data *
331 * *
332 * Purpose: sends 'proxy data' request to server *
333 * *
334 * Parameters: sock - [IN] the connection socket *
335 * ts - [IN] the connection timestamp *
336 * *
337 ******************************************************************************/
zbx_send_task_data(zbx_socket_t * sock,zbx_timespec_t * ts)338 void zbx_send_task_data(zbx_socket_t *sock, zbx_timespec_t *ts)
339 {
340 struct zbx_json j;
341 char *error = NULL, *buffer = NULL;
342 zbx_vector_ptr_t tasks;
343 struct zbx_json_parse jp, jp_tasks;
344 size_t buffer_size, reserved;
345
346 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
347
348 if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "proxy data request"))
349 {
350 /* do not send any reply to server in this case as the server expects proxy data */
351 goto out;
352 }
353
354 zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
355
356 zbx_vector_ptr_create(&tasks);
357 zbx_tm_get_remote_tasks(&tasks, 0);
358
359 if (0 != tasks.values_num)
360 zbx_tm_json_serialize_tasks(&j, &tasks);
361
362 zbx_json_addstring(&j, ZBX_PROTO_TAG_VERSION, ZABBIX_VERSION, ZBX_JSON_TYPE_STRING);
363 zbx_json_adduint64(&j, ZBX_PROTO_TAG_CLOCK, ts->sec);
364 zbx_json_adduint64(&j, ZBX_PROTO_TAG_NS, ts->ns);
365
366 if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size))
367 {
368 zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror());
369 goto clean;
370 }
371
372 reserved = j.buffer_size;
373 zbx_json_free(&j); /* json buffer can be large, free as fast as possible */
374
375 if (SUCCEED == send_data_to_server(sock, &buffer, buffer_size, reserved, &error))
376 {
377 DBbegin();
378
379 if (0 != tasks.values_num)
380 {
381 zbx_tm_update_task_status(&tasks, ZBX_TM_STATUS_DONE);
382 zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
383 }
384
385 if (SUCCEED == zbx_json_open(sock->buffer, &jp))
386 {
387 if (SUCCEED == zbx_json_brackets_by_name(&jp, ZBX_PROTO_TAG_TASKS, &jp_tasks))
388 {
389 zbx_tm_json_deserialize_tasks(&jp_tasks, &tasks);
390 zbx_tm_save_tasks(&tasks);
391 }
392 }
393
394 DBcommit();
395 }
396 else
397 {
398 zabbix_log(LOG_LEVEL_WARNING, "cannot send task data to server at \"%s\": %s", sock->peer, error);
399 zbx_free(error);
400 }
401 clean:
402 zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
403 zbx_vector_ptr_destroy(&tasks);
404
405 zbx_json_free(&j);
406 out:
407 zbx_free(buffer);
408 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
409 }
410
init_proxy_history_lock(char ** error)411 int init_proxy_history_lock(char **error)
412 {
413 if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
414 return zbx_mutex_create(&proxy_lock, ZBX_MUTEX_PROXY_HISTORY, error);
415
416 return SUCCEED;
417 }
418
free_proxy_history_lock(void)419 void free_proxy_history_lock(void)
420 {
421 if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
422 zbx_mutex_destroy(&proxy_lock);
423 }
424
425