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 "zbxreport.h"
22 #include "report_protocol.h"
23 #include "zbxipcservice.h"
24 #include "zbxserialize.h"
25 #include "zbxalgo.h"
26 #include "db.h"
27 #include "zbxalert.h"
28
json_uint_by_tag(const struct zbx_json_parse * jp,const char * tag,zbx_uint64_t * value,char ** error)29 static int json_uint_by_tag(const struct zbx_json_parse *jp, const char *tag, zbx_uint64_t *value, char **error)
30 {
31 char buf[MAX_ID_LEN + 1];
32
33 if (SUCCEED != zbx_json_value_by_name(jp, tag, buf, sizeof(buf), NULL))
34 {
35 *error = zbx_dsprintf(*error, "cannot find tag: %s", tag);
36 return FAIL;
37 }
38
39 if (SUCCEED != is_uint64(buf, value))
40 {
41 *error = zbx_dsprintf(*error, "invalid tag %s value: %s", tag, buf);
42 return FAIL;
43 }
44
45 return SUCCEED;
46 }
47
48 /******************************************************************************
49 * *
50 * ZBX_IPC_REPORTER_TEST_REPORT message serialization/deserialization *
51 * *
52 ******************************************************************************/
53
report_serialize_test_report(unsigned char ** data,const char * name,zbx_uint64_t dashboardid,zbx_uint64_t userid,zbx_uint64_t viewer_userid,int report_time,unsigned char period,const zbx_vector_ptr_pair_t * params)54 static zbx_uint32_t report_serialize_test_report(unsigned char **data, const char *name, zbx_uint64_t dashboardid,
55 zbx_uint64_t userid, zbx_uint64_t viewer_userid, int report_time, unsigned char period,
56 const zbx_vector_ptr_pair_t *params)
57 {
58 zbx_uint32_t data_len = 0, *len, name_len;
59 int i;
60 unsigned char *ptr;
61
62 zbx_serialize_prepare_str(data_len, name);
63 zbx_serialize_prepare_value(data_len, dashboardid);
64 zbx_serialize_prepare_value(data_len, userid);
65 zbx_serialize_prepare_value(data_len, viewer_userid);
66 zbx_serialize_prepare_value(data_len, report_time);
67 zbx_serialize_prepare_value(data_len, period);
68 zbx_serialize_prepare_value(data_len, params->values_num);
69
70 len = (zbx_uint32_t *)zbx_malloc(NULL, params->values_num * 2 * sizeof(zbx_uint32_t));
71
72 for (i = 0; i < params->values_num; i++)
73 {
74 zbx_serialize_prepare_str_len(data_len, params->values[i].first, len[i * 2]);
75 zbx_serialize_prepare_str_len(data_len, params->values[i].second, len[i * 2 + 1]);
76 }
77
78 *data = (unsigned char *)zbx_malloc(NULL, data_len);
79 ptr = *data;
80
81 ptr += zbx_serialize_str(ptr, name, name_len);
82 ptr += zbx_serialize_value(ptr, dashboardid);
83 ptr += zbx_serialize_value(ptr, userid);
84 ptr += zbx_serialize_value(ptr, viewer_userid);
85 ptr += zbx_serialize_value(ptr, report_time);
86 ptr += zbx_serialize_value(ptr, period);
87 ptr += zbx_serialize_value(ptr, params->values_num);
88
89 for (i = 0; i < params->values_num; i++)
90 {
91 ptr += zbx_serialize_str(ptr, params->values[i].first, len[i * 2]);
92 ptr += zbx_serialize_str(ptr, params->values[i].second, len[i * 2 + 1]);
93 }
94
95 zbx_free(len);
96
97 return data_len;
98 }
99
report_deserialize_test_report(const unsigned char * data,char ** name,zbx_uint64_t * dashboardid,zbx_uint64_t * userid,zbx_uint64_t * viewer_userid,int * report_time,unsigned char * period,zbx_vector_ptr_pair_t * params)100 void report_deserialize_test_report(const unsigned char *data, char **name, zbx_uint64_t *dashboardid,
101 zbx_uint64_t *userid, zbx_uint64_t *viewer_userid, int *report_time, unsigned char *period,
102 zbx_vector_ptr_pair_t *params)
103 {
104 int params_num, i;
105 zbx_uint32_t len;
106
107 data += zbx_deserialize_str(data, name, len);
108 data += zbx_deserialize_value(data, dashboardid);
109 data += zbx_deserialize_value(data, userid);
110 data += zbx_deserialize_value(data, viewer_userid);
111 data += zbx_deserialize_value(data, report_time);
112 data += zbx_deserialize_value(data, period);
113 data += zbx_deserialize_value(data, ¶ms_num);
114
115 zbx_vector_ptr_pair_reserve(params, (size_t)params_num);
116 for (i = 0; i < params_num; i++)
117 {
118 zbx_ptr_pair_t pair;
119
120 data += zbx_deserialize_str(data, (char **)&pair.first, len);
121 data += zbx_deserialize_str(data, (char **)&pair.second, len);
122 zbx_vector_ptr_pair_append(params, pair);
123 }
124 }
125
126 #include "log.h"
127
128 /******************************************************************************
129 * *
130 * ZBX_IPC_REPORTER_TEST_REPORT_RESULT, ZBX_IPC_REPORTER_REPORT_RESULT *
131 * message serialization/deserialization *
132 * *
133 ******************************************************************************/
134
report_serialize_response(unsigned char ** data,int status,const char * error,const zbx_vector_ptr_t * results)135 zbx_uint32_t report_serialize_response(unsigned char **data, int status, const char *error,
136 const zbx_vector_ptr_t *results)
137 {
138 zbx_uint32_t data_len = 0, error_len, *recipient_len, *info_len;
139 unsigned char *ptr;
140 int i;
141 zbx_alerter_dispatch_result_t *result;
142
143 zbx_serialize_prepare_value(data_len, status);
144 zbx_serialize_prepare_str(data_len, error);
145
146 if (SUCCEED == status)
147 {
148 zbx_serialize_prepare_value(data_len, results->values_num);
149 recipient_len = (zbx_uint32_t *)zbx_malloc(NULL, sizeof(zbx_uint32_t) * results->values_num);
150 info_len = (zbx_uint32_t *)zbx_malloc(NULL, sizeof(zbx_uint32_t) * results->values_num);
151
152 for (i = 0; i < results->values_num; i++)
153 {
154 result = (zbx_alerter_dispatch_result_t *)results->values[i];
155 zbx_serialize_prepare_value(data_len, result->status);
156 zbx_serialize_prepare_str_len(data_len, result->recipient, recipient_len[i]);
157 zbx_serialize_prepare_str_len(data_len, result->info, info_len[i]);
158 }
159 }
160 else
161 {
162 i = 0;
163 zbx_serialize_prepare_value(data_len, i);
164 }
165
166 *data = (unsigned char *)zbx_malloc(NULL, data_len);
167 ptr = *data;
168
169 ptr += zbx_serialize_value(ptr, status);
170 ptr += zbx_serialize_str(ptr, error, error_len);
171
172 if (SUCCEED == status)
173 {
174 ptr += zbx_serialize_value(ptr, results->values_num);
175
176 for (i = 0; i < results->values_num; i++)
177 {
178 result = (zbx_alerter_dispatch_result_t *)results->values[i];
179 ptr += zbx_serialize_value(ptr, result->status);
180 ptr += zbx_serialize_str(ptr, result->recipient, recipient_len[i]);
181 ptr += zbx_serialize_str(ptr, result->info, info_len[i]);
182 }
183
184 zbx_free(info_len);
185 zbx_free(recipient_len);
186 }
187 else
188 (void)zbx_serialize_value(ptr, i);
189
190 return data_len;
191 }
192
report_deserialize_response(const unsigned char * data,int * status,char ** error,zbx_vector_ptr_t * results)193 void report_deserialize_response(const unsigned char *data, int *status, char **error, zbx_vector_ptr_t *results)
194 {
195 zbx_uint32_t len;
196
197 data += zbx_deserialize_value(data, status);
198 data += zbx_deserialize_str(data, error, len);
199
200 if (SUCCEED == *status && NULL != results)
201 {
202 int i, results_num;
203 zbx_alerter_dispatch_result_t *result;
204
205 data += zbx_deserialize_value(data, &results_num);
206
207 if (0 != results_num)
208 {
209 zbx_vector_ptr_reserve(results, (size_t)results_num);
210
211 for (i = 0; i < results_num; i++)
212 {
213 result = zbx_malloc(NULL, sizeof(zbx_alerter_dispatch_result_t));
214 data += zbx_deserialize_value(data, &result->status);
215 data += zbx_deserialize_str(data, &result->recipient, len);
216 data += zbx_deserialize_str(data, &result->info, len);
217 zbx_vector_ptr_append(results, result);
218 }
219 }
220 }
221 }
222
223 /******************************************************************************
224 * *
225 * ZBX_IPC_REPORTER_BEGIN_REPORT message serialization/deserialization *
226 * *
227 ******************************************************************************/
228
report_serialize_begin_report(unsigned char ** data,const char * name,const char * url,const char * cookie,int width,int height,const zbx_vector_ptr_pair_t * params)229 zbx_uint32_t report_serialize_begin_report(unsigned char **data, const char *name, const char *url,
230 const char *cookie, int width, int height, const zbx_vector_ptr_pair_t *params)
231 {
232 zbx_uint32_t data_len = 0, *params_len, url_len, cookie_len, name_len;
233 unsigned char *ptr;
234 int i;
235
236 zbx_serialize_prepare_str(data_len, name);
237 zbx_serialize_prepare_str(data_len, url);
238 zbx_serialize_prepare_str(data_len, cookie);
239 zbx_serialize_prepare_value(data_len, width);
240 zbx_serialize_prepare_value(data_len, height);
241 zbx_serialize_prepare_value(data_len, params->values_num);
242
243 params_len = (zbx_uint32_t *)zbx_malloc(NULL, params->values_num * 2 * sizeof(zbx_uint32_t));
244 for (i = 0; i < params->values_num; i++)
245 {
246 zbx_serialize_prepare_str_len(data_len, params->values[i].first, params_len[i * 2]);
247 zbx_serialize_prepare_str_len(data_len, params->values[i].second, params_len[i * 2 + 1]);
248 }
249
250 *data = (unsigned char *)zbx_malloc(NULL, data_len);
251 ptr = *data;
252
253 ptr += zbx_serialize_str(ptr, name, name_len);
254 ptr += zbx_serialize_str(ptr, url, url_len);
255 ptr += zbx_serialize_str(ptr, cookie, cookie_len);
256 ptr += zbx_serialize_value(ptr, width);
257 ptr += zbx_serialize_value(ptr, height);
258
259 ptr += zbx_serialize_value(ptr, params->values_num);
260
261 for (i = 0; i < params->values_num; i++)
262 {
263 ptr += zbx_serialize_str(ptr, params->values[i].first, params_len[i * 2]);
264 ptr += zbx_serialize_str(ptr, params->values[i].second, params_len[i * 2 + 1]);
265 }
266
267 zbx_free(params_len);
268
269 return data_len;
270 }
271
report_deserialize_begin_report(const unsigned char * data,char ** name,char ** url,char ** cookie,int * width,int * height,zbx_vector_ptr_pair_t * params)272 void report_deserialize_begin_report(const unsigned char *data, char **name, char **url, char **cookie,
273 int *width, int *height, zbx_vector_ptr_pair_t *params)
274 {
275 zbx_uint32_t len;
276 int i, params_num;
277
278 data += zbx_deserialize_str(data, name, len);
279 data += zbx_deserialize_str(data, url, len);
280 data += zbx_deserialize_str(data, cookie, len);
281 data += zbx_deserialize_value(data, width);
282 data += zbx_deserialize_value(data, height);
283
284 data += zbx_deserialize_value(data, ¶ms_num);
285 zbx_vector_ptr_pair_reserve(params, (size_t)params_num);
286 for (i = 0; i < params_num; i++)
287 {
288 zbx_ptr_pair_t pair;
289
290 data += zbx_deserialize_str(data, (char **)&pair.first, len);
291 data += zbx_deserialize_str(data, (char **)&pair.second, len);
292 zbx_vector_ptr_pair_append(params, pair);
293 }
294 }
295
296 /******************************************************************************
297 * *
298 * ZBX_IPC_REPORTER_SEND_REPORT message serialization/deserialization *
299 * *
300 ******************************************************************************/
301
report_serialize_send_report(unsigned char ** data,const DB_MEDIATYPE * mt,const zbx_vector_str_t * emails)302 zbx_uint32_t report_serialize_send_report(unsigned char **data, const DB_MEDIATYPE *mt,
303 const zbx_vector_str_t *emails)
304 {
305 zbx_uint32_t data_len = 0, data_alloc = 1024, data_offset = 0, *params_len;
306 unsigned char *ptr;
307 int i;
308
309 *data = zbx_malloc(NULL, data_alloc);
310 zbx_serialize_mediatype(data, &data_alloc, &data_offset, mt);
311
312 zbx_serialize_prepare_value(data_len, emails->values_num);
313 params_len = (zbx_uint32_t *)zbx_malloc(NULL, emails->values_num * sizeof(zbx_uint32_t));
314 for (i = 0; i < emails->values_num; i++)
315 {
316 zbx_serialize_prepare_str_len(data_len, emails->values[i], params_len[i]);
317 }
318
319 if (data_alloc - data_offset < data_len)
320 {
321 data_alloc = data_offset + data_len;
322 *data = (unsigned char *)zbx_realloc(*data, data_alloc);
323 }
324
325 ptr = *data + data_offset;
326 ptr += zbx_serialize_value(ptr, emails->values_num);
327 for (i = 0; i < emails->values_num; i++)
328 {
329 ptr += zbx_serialize_str(ptr, emails->values[i], params_len[i]);
330 }
331
332 zbx_free(params_len);
333
334 return data_offset + data_len;
335 }
336
report_deserialize_send_report(const unsigned char * data,DB_MEDIATYPE * mt,zbx_vector_str_t * sendtos)337 void report_deserialize_send_report(const unsigned char *data, DB_MEDIATYPE *mt, zbx_vector_str_t *sendtos)
338 {
339 zbx_uint32_t len;
340 int i, sendto_num;
341
342 data += zbx_deserialize_mediatype(data, mt);
343
344 data += zbx_deserialize_value(data, &sendto_num);
345 zbx_vector_str_reserve(sendtos, (size_t)sendto_num);
346 for (i = 0; i < sendto_num; i++)
347 {
348 char *sendto;
349
350 data += zbx_deserialize_str(data, &sendto, len);
351 zbx_vector_str_append(sendtos, sendto);
352 }
353 }
354
report_clear_ptr_pairs(zbx_vector_ptr_pair_t * params)355 static void report_clear_ptr_pairs(zbx_vector_ptr_pair_t *params)
356 {
357 int i;
358
359 for (i = 0; i < params->values_num; i++)
360 {
361 zbx_free(params->values[i].first);
362 zbx_free(params->values[i].second);
363 }
364 }
365
report_clear_params(zbx_vector_ptr_pair_t * params)366 void report_clear_params(zbx_vector_ptr_pair_t *params)
367 {
368 report_clear_ptr_pairs(params);
369 zbx_vector_ptr_pair_clear(params);
370 }
371
report_destroy_params(zbx_vector_ptr_pair_t * params)372 void report_destroy_params(zbx_vector_ptr_pair_t *params)
373 {
374 report_clear_ptr_pairs(params);
375 zbx_vector_ptr_pair_destroy(params);
376 }
377
zbx_report_test(const struct zbx_json_parse * jp,zbx_uint64_t userid,struct zbx_json * j)378 void zbx_report_test(const struct zbx_json_parse *jp, zbx_uint64_t userid, struct zbx_json *j)
379 {
380 zbx_uint64_t dashboardid, viewer_userid, ui64;
381 int ret = FAIL, period, report_time;
382 struct zbx_json_parse jp_params;
383 zbx_vector_ptr_pair_t params;
384 zbx_vector_ptr_t results;
385 zbx_uint32_t size;
386 unsigned char *data = NULL, *response = NULL;
387 char *name = NULL, *error = NULL;
388 size_t name_alloc = 0;
389
390 zbx_vector_ptr_pair_create(¶ms);
391 zbx_vector_ptr_create(&results);
392
393 if (SUCCEED != zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_NAME, &name, &name_alloc, NULL))
394 {
395 error = zbx_dsprintf(error, "cannot find tag: %s", ZBX_PROTO_TAG_NAME);
396 goto out;
397 }
398
399 if (SUCCEED != json_uint_by_tag(jp, ZBX_PROTO_TAG_DASHBOARDID, &dashboardid, &error))
400 goto out;
401
402 if (SUCCEED != json_uint_by_tag(jp, ZBX_PROTO_TAG_USERID, &viewer_userid, &error))
403 goto out;
404
405 if (SUCCEED != json_uint_by_tag(jp, ZBX_PROTO_TAG_PERIOD, &ui64, &error))
406 goto out;
407 period = (int)ui64;
408
409 if (SUCCEED != json_uint_by_tag(jp, ZBX_PROTO_TAG_NOW, &ui64, &error))
410 goto out;
411 report_time = (int)ui64;
412
413 if (SUCCEED == zbx_json_brackets_by_name(jp, ZBX_PROTO_TAG_PARAMS, &jp_params))
414 {
415 const char *pnext = NULL;
416 char key[MAX_STRING_LEN];
417
418 while (NULL != (pnext = zbx_json_pair_next(&jp_params, pnext, key, sizeof(key))))
419 {
420 char *value = NULL;
421 size_t value_alloc = 0;
422 zbx_ptr_pair_t pair;
423
424 zbx_json_decodevalue_dyn(pnext, &value, &value_alloc, NULL);
425 pair.first = zbx_strdup(NULL, key);
426 pair.second = value;
427 zbx_vector_ptr_pair_append(¶ms, pair);
428 }
429 }
430
431 size = report_serialize_test_report(&data, name, dashboardid, userid, viewer_userid, report_time, period,
432 ¶ms);
433
434 if (SUCCEED != zbx_ipc_async_exchange(ZBX_IPC_SERVICE_REPORTER, ZBX_IPC_REPORTER_TEST,
435 SEC_PER_MIN, data, size, &response, &error))
436 {
437 goto out;
438 }
439
440 report_deserialize_response(response, &ret, &error, &results);
441 out:
442 zbx_json_init(j, 1024);
443
444 if (SUCCEED == ret)
445 {
446 int i;
447 zbx_alerter_dispatch_result_t *result;
448
449 zbx_json_addstring(j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
450 zbx_json_addobject(j, ZBX_PROTO_TAG_DATA);
451 zbx_json_addarray(j, ZBX_PROTO_TAG_RECIPIENTS);
452
453 for (i = 0; i < results.values_num; i++)
454 {
455 zbx_json_addobject(j, NULL);
456
457 result = (zbx_alerter_dispatch_result_t *)results.values[i];
458 zbx_json_addint64(j, ZBX_PROTO_TAG_STATUS, result->status);
459 zbx_json_addstring(j, ZBX_PROTO_TAG_RECIPIENT, result->recipient, ZBX_JSON_TYPE_STRING);
460 if (NULL != result->info)
461 zbx_json_addstring(j, ZBX_PROTO_TAG_INFO, result->info, ZBX_JSON_TYPE_STRING);
462
463 zbx_json_close(j);
464 }
465 }
466 else
467 {
468 zbx_json_addstring(j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING);
469 zbx_json_addstring(j, ZBX_PROTO_TAG_INFO, error, ZBX_JSON_TYPE_STRING);
470 }
471
472 zbx_free(error);
473 zbx_free(response);
474 zbx_free(data);
475 zbx_free(name);
476
477 zbx_vector_ptr_clear_ext(&results, (zbx_clean_func_t)zbx_alerter_dispatch_result_free);
478 zbx_vector_ptr_destroy(&results);
479 report_destroy_params(¶ms);
480 }
481