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 <assert.h>
21 
22 #include "common.h"
23 #include "log.h"
24 
25 #include "db.h"
26 #include "zbxjson.h"
27 #include "zbxtasks.h"
28 
29 /******************************************************************************
30  *                                                                            *
31  * Function: tm_remote_command_clear                                          *
32  *                                                                            *
33  * Purpose: frees remote command task resources                               *
34  *                                                                            *
35  * Parameters: data - [IN] the remote command task data                       *
36  *                                                                            *
37  ******************************************************************************/
tm_remote_command_clear(zbx_tm_remote_command_t * data)38 static void	tm_remote_command_clear(zbx_tm_remote_command_t *data)
39 {
40 	zbx_free(data->command);
41 	zbx_free(data->username);
42 	zbx_free(data->password);
43 	zbx_free(data->publickey);
44 	zbx_free(data->privatekey);
45 }
46 
47 /******************************************************************************
48  *                                                                            *
49  * Function: tm_remote_command_result_clear                                   *
50  *                                                                            *
51  * Purpose: frees remote command result task resources                        *
52  *                                                                            *
53  * Parameters: data - [IN] the remote command result task data                *
54  *                                                                            *
55  ******************************************************************************/
tm_remote_command_result_clear(zbx_tm_remote_command_result_t * data)56 static void	tm_remote_command_result_clear(zbx_tm_remote_command_result_t *data)
57 {
58 	zbx_free(data->info);
59 }
60 
61 /******************************************************************************
62  *                                                                            *
63  * Function: zbx_tm_task_clear                                                *
64  *                                                                            *
65  * Purpose: frees task resources                                              *
66  *                                                                            *
67  * Parameters: task - [IN]                                                    *
68  *                                                                            *
69  ******************************************************************************/
zbx_tm_task_clear(zbx_tm_task_t * task)70 void	zbx_tm_task_clear(zbx_tm_task_t *task)
71 {
72 	if (NULL != task->data)
73 	{
74 		switch (task->type)
75 		{
76 			case ZBX_TM_TASK_REMOTE_COMMAND:
77 				tm_remote_command_clear((zbx_tm_remote_command_t *)task->data);
78 				break;
79 			case ZBX_TM_TASK_REMOTE_COMMAND_RESULT:
80 				tm_remote_command_result_clear((zbx_tm_remote_command_result_t *)task->data);
81 				break;
82 			case ZBX_TM_TASK_CHECK_NOW:
83 				/* nothing to clear */
84 				break;
85 			default:
86 				THIS_SHOULD_NEVER_HAPPEN;
87 		}
88 	}
89 
90 	zbx_free(task->data);
91 	task->type = ZBX_TM_TASK_UNDEFINED;
92 }
93 
94 /******************************************************************************
95  *                                                                            *
96  * Function: zbx_tm_task_free                                                 *
97  *                                                                            *
98  * Purpose: frees task and its resources                                      *
99  *                                                                            *
100  * Parameters: task - [IN] the task to free                                   *
101  *                                                                            *
102  ******************************************************************************/
zbx_tm_task_free(zbx_tm_task_t * task)103 void	zbx_tm_task_free(zbx_tm_task_t *task)
104 {
105 	zbx_tm_task_clear(task);
106 	zbx_free(task);
107 }
108 
109 /******************************************************************************
110  *                                                                            *
111  * Function: zbx_tm_remote_command_create                                     *
112  *                                                                            *
113  * Purpose: create a remote command task data                                 *
114  *                                                                            *
115  * Parameters: command_type  - [IN] the remote command type (ZBX_SCRIPT_TYPE_)*
116  *             command       - [IN] the command to execute                    *
117  *             execute_on    - [IN] the execution target (ZBX_SCRIPT_EXECUTE_)*
118  *             port          - [IN] the target port                           *
119  *             authtype      - [IN] the authentication type                   *
120  *             username      - [IN] the username (can be NULL)                *
121  *             password      - [IN] the password (can be NULL)                *
122  *             publickey     - [IN] the public key (can be NULL)              *
123  *             privatekey    - [IN] the private key (can be NULL)             *
124  *             parent_taskid - [IN] the parent task identifier                *
125  *             hostid        - [IN] the target host identifier                *
126  *             alertid       - [IN] the alert identifier                      *
127  *                                                                            *
128  * Return value: The created remote command data.                             *
129  *                                                                            *
130  ******************************************************************************/
zbx_tm_remote_command_create(int command_type,const char * command,int execute_on,int port,int authtype,const char * username,const char * password,const char * publickey,const char * privatekey,zbx_uint64_t parent_taskid,zbx_uint64_t hostid,zbx_uint64_t alertid)131 zbx_tm_remote_command_t	*zbx_tm_remote_command_create(int command_type, const char *command, int execute_on, int port,
132 		int authtype, const char *username, const char *password, const char *publickey, const char *privatekey,
133 		zbx_uint64_t parent_taskid, zbx_uint64_t hostid, zbx_uint64_t alertid)
134 {
135 	zbx_tm_remote_command_t	*data;
136 
137 	data = (zbx_tm_remote_command_t *)zbx_malloc(NULL, sizeof(zbx_tm_remote_command_t));
138 	data->command_type = command_type;
139 	data->command = zbx_strdup(NULL, ZBX_NULL2EMPTY_STR(command));
140 	data->execute_on = execute_on;
141 	data->port = port;
142 	data->authtype = authtype;
143 	data->username = zbx_strdup(NULL, ZBX_NULL2EMPTY_STR(username));
144 	data->password = zbx_strdup(NULL, ZBX_NULL2EMPTY_STR(password));
145 	data->publickey = zbx_strdup(NULL, ZBX_NULL2EMPTY_STR(publickey));
146 	data->privatekey = zbx_strdup(NULL, ZBX_NULL2EMPTY_STR(privatekey));
147 	data->parent_taskid = parent_taskid;
148 	data->hostid = hostid;
149 	data->alertid = alertid;
150 
151 	return data;
152 }
153 
154 /******************************************************************************
155  *                                                                            *
156  * Function: zbx_tm_remote_command_result_create                              *
157  *                                                                            *
158  * Purpose: create a remote command result task data                          *
159  *                                                                            *
160  * Parameters: parent_taskid - [IN] the parent task identifier                *
161  *             status        - [IN] the remote command execution status       *
162  *             info          - [IN] the remote command execution result       *
163  *                                                                            *
164  * Return value: The created remote command result data.                      *
165  *                                                                            *
166  ******************************************************************************/
zbx_tm_remote_command_result_create(zbx_uint64_t parent_taskid,int status,const char * info)167 zbx_tm_remote_command_result_t	*zbx_tm_remote_command_result_create(zbx_uint64_t parent_taskid, int status,
168 		const char *info)
169 {
170 	zbx_tm_remote_command_result_t	*data;
171 
172 	data = (zbx_tm_remote_command_result_t *)zbx_malloc(NULL, sizeof(zbx_tm_remote_command_result_t));
173 	data->status = status;
174 	data->parent_taskid = parent_taskid;
175 	data->info = zbx_strdup(NULL, ZBX_NULL2EMPTY_STR(info));
176 
177 	return data;
178 }
179 
180 /******************************************************************************
181  *                                                                            *
182  * Function: zbx_tm_check_now_create                                          *
183  *                                                                            *
184  * Purpose: create a check now task data                                      *
185  *                                                                            *
186  * Parameters: itemid - [IN] the item identifier                              *
187  *                                                                            *
188  * Return value: The created check now data.                                  *
189  *                                                                            *
190  ******************************************************************************/
zbx_tm_check_now_create(zbx_uint64_t itemid)191 zbx_tm_check_now_t	*zbx_tm_check_now_create(zbx_uint64_t itemid)
192 {
193 	zbx_tm_check_now_t	*data;
194 
195 	data = (zbx_tm_check_now_t *)zbx_malloc(NULL, sizeof(zbx_tm_check_now_t));
196 	data->itemid = itemid;
197 
198 	return data;
199 }
200 
201 /******************************************************************************
202  *                                                                            *
203  * Function: zbx_tm_task_create                                               *
204  *                                                                            *
205  * Purpose: create a new task                                                 *
206  *                                                                            *
207  * Parameters: taskid       - [IN] the task identifier                        *
208  *             type         - [IN] the task type (see ZBX_TM_TASK_*)          *
209  *             status       - [IN] the task status (see ZBX_TM_STATUS_*)      *
210  *             clock        - [IN] the task creation time                     *
211  *             ttl          - [IN] the task expiration period in seconds      *
212  *             proxy_hostid - [IN] the destination proxy identifier (or 0)    *
213  *                                                                            *
214  * Return value: The created task.                                            *
215  *                                                                            *
216  ******************************************************************************/
zbx_tm_task_create(zbx_uint64_t taskid,unsigned char type,unsigned char status,int clock,int ttl,zbx_uint64_t proxy_hostid)217 zbx_tm_task_t	*zbx_tm_task_create(zbx_uint64_t taskid, unsigned char type, unsigned char status, int clock, int ttl,
218 		zbx_uint64_t proxy_hostid)
219 {
220 	zbx_tm_task_t	*task;
221 
222 	task = (zbx_tm_task_t *)zbx_malloc(NULL, sizeof(zbx_tm_task_t));
223 
224 	task->taskid = taskid;
225 	task->type = type;
226 	task->status = status;
227 	task->clock = clock;
228 	task->ttl = ttl;
229 	task->proxy_hostid = proxy_hostid;
230 	task->data = NULL;
231 
232 	return task;
233 }
234 
235 /******************************************************************************
236  *                                                                            *
237  * Function: tm_save_remote_command_tasks                                     *
238  *                                                                            *
239  * Purpose: saves remote command task data in database                        *
240  *                                                                            *
241  * Parameters: tasks     - [IN] the tasks                                     *
242  *             tasks_num - [IN] the number of tasks to process                *
243  *                                                                            *
244  * Return value: SUCCEED - the data was saved successfully                    *
245  *               FAIL    - otherwise                                          *
246  *                                                                            *
247  * Comments: The tasks array can contain mixture of task types.               *
248  *                                                                            *
249  ******************************************************************************/
tm_save_remote_command_tasks(zbx_tm_task_t ** tasks,int tasks_num)250 static int	tm_save_remote_command_tasks(zbx_tm_task_t **tasks, int tasks_num)
251 {
252 	int			i, ret;
253 	zbx_db_insert_t		db_insert;
254 	zbx_tm_remote_command_t	*data;
255 
256 	zbx_db_insert_prepare(&db_insert, "task_remote_command", "taskid", "command_type", "execute_on", "port",
257 			"authtype", "username", "password", "publickey", "privatekey", "command", "alertid",
258 			"parent_taskid", "hostid", NULL);
259 
260 	for (i = 0; i < tasks_num; i++)
261 	{
262 		zbx_tm_task_t	*task = tasks[i];
263 
264 		switch (task->type)
265 		{
266 			case ZBX_TM_TASK_REMOTE_COMMAND:
267 				data = (zbx_tm_remote_command_t *)task->data;
268 				zbx_db_insert_add_values(&db_insert, task->taskid, data->command_type, data->execute_on,
269 						data->port, data->authtype, data->username, data->password,
270 						data->publickey, data->privatekey, data->command, data->alertid,
271 						data->parent_taskid, data->hostid);
272 		}
273 	}
274 
275 	ret = zbx_db_insert_execute(&db_insert);
276 	zbx_db_insert_clean(&db_insert);
277 
278 	return ret;
279 }
280 
281 /******************************************************************************
282  *                                                                            *
283  * Function: tm_save_remote_command_result_tasks                              *
284  *                                                                            *
285  * Purpose: saves remote command result task data in database                 *
286  *                                                                            *
287  * Parameters: tasks     - [IN] the tasks                                     *
288  *             tasks_num - [IN] the number of tasks to process                *
289  *                                                                            *
290  * Return value: SUCCEED - the data was saved successfully                    *
291  *               FAIL    - otherwise                                          *
292  *                                                                            *
293  * Comments: The tasks array can contain mixture of task types.               *
294  *                                                                            *
295  ******************************************************************************/
tm_save_remote_command_result_tasks(zbx_tm_task_t ** tasks,int tasks_num)296 static int	tm_save_remote_command_result_tasks(zbx_tm_task_t **tasks, int tasks_num)
297 {
298 	int				i, ret;
299 	zbx_db_insert_t			db_insert;
300 	zbx_tm_remote_command_result_t	*data;
301 
302 	zbx_db_insert_prepare(&db_insert, "task_remote_command_result", "taskid", "status", "parent_taskid", "info",
303 			NULL);
304 
305 	for (i = 0; i < tasks_num; i++)
306 	{
307 		zbx_tm_task_t	*task = tasks[i];
308 
309 		switch (task->type)
310 		{
311 			case ZBX_TM_TASK_REMOTE_COMMAND_RESULT:
312 				data = (zbx_tm_remote_command_result_t *)task->data;
313 				zbx_db_insert_add_values(&db_insert, task->taskid, data->status, data->parent_taskid,
314 						data->info);
315 		}
316 	}
317 
318 	ret = zbx_db_insert_execute(&db_insert);
319 	zbx_db_insert_clean(&db_insert);
320 
321 	return ret;
322 }
323 
324 /******************************************************************************
325  *                                                                            *
326  * Function: tm_save_check_now_tasks                                          *
327  *                                                                            *
328  * Purpose: saves remote command task data in database                        *
329  *                                                                            *
330  * Parameters: tasks     - [IN] the tasks                                     *
331  *             tasks_num - [IN] the number of tasks to process                *
332  *                                                                            *
333  * Return value: SUCCEED - the data was saved successfully                    *
334  *               FAIL    - otherwise                                          *
335  *                                                                            *
336  * Comments: The tasks array can contain mixture of task types.               *
337  *                                                                            *
338  ******************************************************************************/
tm_save_check_now_tasks(zbx_tm_task_t ** tasks,int tasks_num)339 static int	tm_save_check_now_tasks(zbx_tm_task_t **tasks, int tasks_num)
340 {
341 	int			i, ret;
342 	zbx_db_insert_t		db_insert;
343 	zbx_tm_check_now_t	*data;
344 
345 	zbx_db_insert_prepare(&db_insert, "task_check_now", "taskid", "itemid", NULL);
346 
347 	for (i = 0; i < tasks_num; i++)
348 	{
349 		const zbx_tm_task_t	*task = tasks[i];
350 
351 		switch (task->type)
352 		{
353 			case ZBX_TM_TASK_CHECK_NOW:
354 				data = (zbx_tm_check_now_t *)task->data;
355 				zbx_db_insert_add_values(&db_insert, task->taskid, data->itemid);
356 		}
357 	}
358 
359 	ret = zbx_db_insert_execute(&db_insert);
360 	zbx_db_insert_clean(&db_insert);
361 
362 	return ret;
363 }
364 
365 /******************************************************************************
366  *                                                                            *
367  * Function: tm_save_tasks                                                    *
368  *                                                                            *
369  * Purpose: saves tasks into database                                         *
370  *                                                                            *
371  * Parameters: tasks     - [IN] the tasks                                     *
372  *             tasks_num - [IN] the number of tasks to process                *
373  *                                                                            *
374  * Return value: SUCCEED - the tasks were saved successfully                  *
375  *               FAIL    - otherwise                                          *
376  *                                                                            *
377  ******************************************************************************/
tm_save_tasks(zbx_tm_task_t ** tasks,int tasks_num)378 static int	tm_save_tasks(zbx_tm_task_t **tasks, int tasks_num)
379 {
380 	int		i, ret, remote_command_num = 0, remote_command_result_num = 0, check_now_num = 0, ids_num = 0;
381 	zbx_uint64_t	taskid;
382 	zbx_db_insert_t	db_insert;
383 
384 	for (i = 0; i < tasks_num; i++)
385 	{
386 		if (0 == tasks[i]->taskid)
387 			ids_num++;
388 	}
389 
390 	if (0 != ids_num)
391 		taskid = DBget_maxid_num("task", ids_num);
392 
393 	for (i = 0; i < tasks_num; i++)
394 	{
395 		switch (tasks[i]->type)
396 		{
397 			case ZBX_TM_TASK_REMOTE_COMMAND:
398 				remote_command_num++;
399 				break;
400 			case ZBX_TM_TASK_REMOTE_COMMAND_RESULT:
401 				remote_command_result_num++;
402 				break;
403 			case ZBX_TM_TASK_CHECK_NOW:
404 				check_now_num++;
405 				break;
406 			default:
407 				THIS_SHOULD_NEVER_HAPPEN;
408 				continue;
409 		}
410 
411 		if (0 == tasks[i]->taskid)
412 			tasks[i]->taskid = taskid++;
413 	}
414 
415 	zbx_db_insert_prepare(&db_insert, "task", "taskid", "type", "status", "clock", "ttl", "proxy_hostid", NULL);
416 
417 	for (i = 0; i < tasks_num; i++)
418 	{
419 		if (0 == tasks[i]->taskid)
420 			continue;
421 
422 		zbx_db_insert_add_values(&db_insert, tasks[i]->taskid, (int)tasks[i]->type, (int)tasks[i]->status,
423 				tasks[i]->clock, tasks[i]->ttl, tasks[i]->proxy_hostid);
424 	}
425 
426 	ret = zbx_db_insert_execute(&db_insert);
427 	zbx_db_insert_clean(&db_insert);
428 
429 	if (SUCCEED == ret && 0 != remote_command_num)
430 		ret = tm_save_remote_command_tasks(tasks, tasks_num);
431 
432 	if (SUCCEED == ret && 0 != remote_command_result_num)
433 		ret = tm_save_remote_command_result_tasks(tasks, tasks_num);
434 
435 	if (SUCCEED == ret && 0 != check_now_num)
436 		ret = tm_save_check_now_tasks(tasks, tasks_num);
437 
438 	return ret;
439 }
440 
441 /******************************************************************************
442  *                                                                            *
443  * Function: zbx_tm_save_tasks                                                *
444  *                                                                            *
445  * Purpose: saves tasks and their data into database                          *
446  *                                                                            *
447  * Parameters: tasks - [IN] the tasks                                         *
448  *                                                                            *
449  ******************************************************************************/
zbx_tm_save_tasks(zbx_vector_ptr_t * tasks)450 void	zbx_tm_save_tasks(zbx_vector_ptr_t *tasks)
451 {
452 	const char	*__function_name = "zbx_tm_save_tasks";
453 
454 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() tasks_num:%d", __function_name, tasks->values_num);
455 
456 	tm_save_tasks((zbx_tm_task_t **)tasks->values, tasks->values_num);
457 
458 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
459 }
460 
461 /******************************************************************************
462  *                                                                            *
463  * Function: zbx_tm_save_task                                                 *
464  *                                                                            *
465  * Purpose: saves task and its data into database                             *
466  *                                                                            *
467  * Parameters: task - [IN] the task                                           *
468  *                                                                            *
469  * Return value: SUCCEED - the task was saved successfully                    *
470  *               FAIL    - otherwise                                          *
471  *                                                                            *
472  ******************************************************************************/
zbx_tm_save_task(zbx_tm_task_t * task)473 int	zbx_tm_save_task(zbx_tm_task_t *task)
474 {
475 	const char	*__function_name = "zbx_tm_save_task";
476 	int		ret;
477 
478 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
479 
480 	ret = tm_save_tasks(&task, 1);
481 
482 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
483 
484 	return ret;
485 }
486 
487 /******************************************************************************
488  *                                                                            *
489  * Function: zbx_tm_update_task_status                                        *
490  *                                                                            *
491  * Purpose: update status of the specified tasks in database                  *
492  *                                                                            *
493  * Parameters: tasks  - [IN] the tasks                                        *
494  *             status - [IN] the new status                                   *
495  *                                                                            *
496  ******************************************************************************/
zbx_tm_update_task_status(zbx_vector_ptr_t * tasks,int status)497 void	zbx_tm_update_task_status(zbx_vector_ptr_t *tasks, int status)
498 {
499 	const char		*__function_name = "zbx_tm_update_task_status";
500 	zbx_vector_uint64_t	taskids;
501 	int			i;
502 	char			*sql = NULL;
503 	size_t			sql_alloc = 0, sql_offset = 0;
504 
505 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
506 
507 	zbx_vector_uint64_create(&taskids);
508 
509 	for (i = 0; i < tasks->values_num; i++)
510 	{
511 		zbx_tm_task_t	*task = (zbx_tm_task_t *)tasks->values[i];
512 		zbx_vector_uint64_append(&taskids, task->taskid);
513 	}
514 
515 	zbx_vector_uint64_sort(&taskids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
516 
517 	zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update task set status=%d where", status);
518 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "taskid", taskids.values, taskids.values_num);
519 	DBexecute("%s", sql);
520 	zbx_free(sql);
521 
522 	zbx_vector_uint64_destroy(&taskids);
523 
524 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
525 }
526 
527 /******************************************************************************
528  *                                                                            *
529  * Function: tm_json_serialize_task                                           *
530  *                                                                            *
531  * Purpose: serializes common task data in json format                        *
532  *                                                                            *
533  * Parameters: json - [OUT] the json data                                     *
534  *             data - [IN] the task to serialize                              *
535  *                                                                            *
536  ******************************************************************************/
tm_json_serialize_task(struct zbx_json * json,const zbx_tm_task_t * task)537 static void	tm_json_serialize_task(struct zbx_json *json, const zbx_tm_task_t *task)
538 {
539 	zbx_json_addint64(json, ZBX_PROTO_TAG_TYPE, task->type);
540 	zbx_json_addint64(json, ZBX_PROTO_TAG_CLOCK, task->clock);
541 	zbx_json_addint64(json, ZBX_PROTO_TAG_TTL, task->ttl);
542 }
543 
544 /******************************************************************************
545  *                                                                            *
546  * Function: tm_json_serialize_remote_command                                 *
547  *                                                                            *
548  * Purpose: serializes remote command data in json format                     *
549  *                                                                            *
550  * Parameters: json - [OUT] the json data                                     *
551  *             data - [IN] the remote command to serialize                    *
552  *                                                                            *
553  ******************************************************************************/
tm_json_serialize_remote_command(struct zbx_json * json,const zbx_tm_remote_command_t * data)554 static void	tm_json_serialize_remote_command(struct zbx_json *json, const zbx_tm_remote_command_t *data)
555 {
556 	zbx_json_addint64(json, ZBX_PROTO_TAG_COMMANDTYPE, data->command_type);
557 	zbx_json_addstring(json, ZBX_PROTO_TAG_COMMAND, data->command, ZBX_JSON_TYPE_STRING);
558 	zbx_json_addint64(json, ZBX_PROTO_TAG_EXECUTE_ON, data->execute_on);
559 	zbx_json_addint64(json, ZBX_PROTO_TAG_PORT, data->port);
560 	zbx_json_addint64(json, ZBX_PROTO_TAG_AUTHTYPE, data->authtype);
561 	zbx_json_addstring(json, ZBX_PROTO_TAG_USERNAME, data->username, ZBX_JSON_TYPE_STRING);
562 	zbx_json_addstring(json, ZBX_PROTO_TAG_PASSWORD, data->password, ZBX_JSON_TYPE_STRING);
563 	zbx_json_addstring(json, ZBX_PROTO_TAG_PUBLICKEY, data->publickey, ZBX_JSON_TYPE_STRING);
564 	zbx_json_addstring(json, ZBX_PROTO_TAG_PRIVATEKEY, data->privatekey, ZBX_JSON_TYPE_STRING);
565 	zbx_json_adduint64(json, ZBX_PROTO_TAG_ALERTID, data->alertid);
566 	zbx_json_adduint64(json, ZBX_PROTO_TAG_PARENT_TASKID, data->parent_taskid);
567 	zbx_json_adduint64(json, ZBX_PROTO_TAG_HOSTID, data->hostid);
568 }
569 
570 /******************************************************************************
571  *                                                                            *
572  * Function: tm_json_serialize_remote_command_result                          *
573  *                                                                            *
574  * Purpose: serializes remote command result data in json format              *
575  *                                                                            *
576  * Parameters: json - [OUT] the json data                                     *
577  *             data - [IN] the remote command result to serialize             *
578  *                                                                            *
579  ******************************************************************************/
tm_json_serialize_remote_command_result(struct zbx_json * json,const zbx_tm_remote_command_result_t * data)580 static void	tm_json_serialize_remote_command_result(struct zbx_json *json,
581 		const zbx_tm_remote_command_result_t *data)
582 {
583 	zbx_json_addint64(json, ZBX_PROTO_TAG_STATUS, data->status);
584 	zbx_json_addstring(json, ZBX_PROTO_TAG_INFO, data->info, ZBX_JSON_TYPE_STRING);
585 	zbx_json_adduint64(json, ZBX_PROTO_TAG_PARENT_TASKID, data->parent_taskid);
586 }
587 
588 /******************************************************************************
589  *                                                                            *
590  * Function: tm_json_serialize_check_now                                      *
591  *                                                                            *
592  * Purpose: serializes check now data in json format                          *
593  *                                                                            *
594  * Parameters: json - [OUT] the json data                                     *
595  *             data - [IN] the check now to serialize                         *
596  *                                                                            *
597  ******************************************************************************/
tm_json_serialize_check_now(struct zbx_json * json,const zbx_tm_check_now_t * data)598 static void	tm_json_serialize_check_now(struct zbx_json *json, const zbx_tm_check_now_t *data)
599 {
600 	zbx_json_addint64(json, ZBX_PROTO_TAG_ITEMID, data->itemid);
601 }
602 
603 /******************************************************************************
604  *                                                                            *
605  * Function: zbx_tm_json_serialize_tasks                                      *
606  *                                                                            *
607  * Purpose: serializes remote command data in json format                     *
608  *                                                                            *
609  * Parameters: json  - [OUT] the json data                                    *
610  *             tasks - [IN] the tasks to serialize                            *
611  *                                                                            *
612  ******************************************************************************/
zbx_tm_json_serialize_tasks(struct zbx_json * json,const zbx_vector_ptr_t * tasks)613 void	zbx_tm_json_serialize_tasks(struct zbx_json *json, const zbx_vector_ptr_t *tasks)
614 {
615 	int	i;
616 
617 	zbx_json_addarray(json, ZBX_PROTO_TAG_TASKS);
618 
619 	for (i = 0; i < tasks->values_num; i++)
620 	{
621 		const zbx_tm_task_t	*task = (const zbx_tm_task_t *)tasks->values[i];
622 
623 		zbx_json_addobject(json, NULL);
624 		tm_json_serialize_task(json, task);
625 
626 		switch (task->type)
627 		{
628 			case ZBX_TM_TASK_REMOTE_COMMAND:
629 				tm_json_serialize_remote_command(json, (zbx_tm_remote_command_t *)task->data);
630 				break;
631 			case ZBX_TM_TASK_REMOTE_COMMAND_RESULT:
632 				tm_json_serialize_remote_command_result(json, (zbx_tm_remote_command_result_t *)task->data);
633 				break;
634 			case ZBX_TM_TASK_CHECK_NOW:
635 				tm_json_serialize_check_now(json, (zbx_tm_check_now_t *)task->data);
636 				break;
637 			default:
638 				THIS_SHOULD_NEVER_HAPPEN;
639 				break;
640 		}
641 
642 		zbx_json_close(json);
643 	}
644 
645 	zbx_json_close(json);
646 }
647 
648 /******************************************************************************
649  *                                                                            *
650  * Function: tm_json_deserialize_remote_command                               *
651  *                                                                            *
652  * Purpose: deserializes remote command from json data                        *
653  *                                                                            *
654  * Parameters: jp - [IN] the json data                                        *
655  *                                                                            *
656  * Return value: The deserialized remote command data or NULL if              *
657  *               deserialization failed.                                      *
658  *                                                                            *
659  ******************************************************************************/
tm_json_deserialize_remote_command(const struct zbx_json_parse * jp)660 static zbx_tm_remote_command_t	*tm_json_deserialize_remote_command(const struct zbx_json_parse *jp)
661 {
662 	char			value[MAX_STRING_LEN];
663 	int			commandtype, execute_on, port, authtype;
664 	zbx_uint64_t		alertid, parent_taskid, hostid;
665 	char			*username = NULL, *password = NULL, *publickey = NULL, *privatekey = NULL,
666 				*command = NULL;
667 	size_t			username_alloc = 0, password_alloc = 0, publickey_alloc = 0, privatekey_alloc = 0,
668 				command_alloc = 0;
669 	zbx_tm_remote_command_t	*data = NULL;
670 
671 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_COMMANDTYPE, value, sizeof(value), NULL))
672 		goto out;
673 
674 	commandtype = atoi(value);
675 
676 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_EXECUTE_ON, value, sizeof(value), NULL))
677 		goto out;
678 
679 	execute_on = atoi(value);
680 
681 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_PORT, value, sizeof(value), NULL))
682 		goto out;
683 
684 	port = atoi(value);
685 
686 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_AUTHTYPE, value, sizeof(value), NULL))
687 		goto out;
688 
689 	authtype = atoi(value);
690 
691 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_ALERTID, value, sizeof(value), NULL) ||
692 			SUCCEED != is_uint64(value, &alertid))
693 	{
694 		goto out;
695 	}
696 
697 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_PARENT_TASKID, value, sizeof(value), NULL) ||
698 			SUCCEED != is_uint64(value, &parent_taskid))
699 	{
700 		goto out;
701 	}
702 
703 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOSTID, value, sizeof(value), NULL) ||
704 			SUCCEED != is_uint64(value, &hostid))
705 	{
706 		goto out;
707 	}
708 
709 	if (SUCCEED != zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_USERNAME, &username, &username_alloc, NULL))
710 		goto out;
711 
712 	if (SUCCEED != zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_PASSWORD, &password, &password_alloc, NULL))
713 		goto out;
714 
715 	if (SUCCEED != zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_PUBLICKEY, &publickey, &publickey_alloc, NULL))
716 		goto out;
717 
718 	if (SUCCEED != zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_PRIVATEKEY, &privatekey, &privatekey_alloc, NULL))
719 		goto out;
720 
721 	if (SUCCEED != zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_COMMAND, &command, &command_alloc, NULL))
722 		goto out;
723 
724 	data = zbx_tm_remote_command_create(commandtype, command, execute_on, port, authtype, username, password,
725 			publickey, privatekey, parent_taskid, hostid, alertid);
726 out:
727 	zbx_free(command);
728 	zbx_free(privatekey);
729 	zbx_free(publickey);
730 	zbx_free(password);
731 	zbx_free(username);
732 
733 	return data;
734 }
735 
736 /******************************************************************************
737  *                                                                            *
738  * Function: tm_json_deserialize_remote_command_result                        *
739  *                                                                            *
740  * Purpose: deserializes remote command result from json data                 *
741  *                                                                            *
742  * Parameters: jp - [IN] the json data                                        *
743  *                                                                            *
744  * Return value: The deserialized remote command result data or NULL if       *
745  *               deserialization failed.                                      *
746  *                                                                            *
747  ******************************************************************************/
tm_json_deserialize_remote_command_result(const struct zbx_json_parse * jp)748 static zbx_tm_remote_command_result_t	*tm_json_deserialize_remote_command_result(const struct zbx_json_parse *jp)
749 {
750 	char				value[MAX_STRING_LEN];
751 	int				status;
752 	zbx_uint64_t			parent_taskid;
753 	char				*info = NULL;
754 	size_t				info_alloc = 0;
755 	zbx_tm_remote_command_result_t	*data = NULL;
756 
757 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_STATUS, value, sizeof(value), NULL))
758 		goto out;
759 
760 	status = atoi(value);
761 
762 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_PARENT_TASKID, value, sizeof(value), NULL) ||
763 			SUCCEED != is_uint64(value, &parent_taskid))
764 	{
765 		goto out;
766 	}
767 
768 	if (SUCCEED != zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_INFO, &info, &info_alloc, NULL))
769 		goto out;
770 
771 	data = zbx_tm_remote_command_result_create(parent_taskid, status, info);
772 out:
773 	zbx_free(info);
774 
775 	return data;
776 }
777 
778 /******************************************************************************
779  *                                                                            *
780  * Function: tm_json_deserialize_check_now                                    *
781  *                                                                            *
782  * Purpose: deserializes check now from json data                             *
783  *                                                                            *
784  * Parameters: jp - [IN] the json data                                        *
785  *                                                                            *
786  * Return value: The deserialized check now data or NULL if deserialization   *
787  *               failed.                                                      *
788  *                                                                            *
789  ******************************************************************************/
tm_json_deserialize_check_now(const struct zbx_json_parse * jp)790 static zbx_tm_check_now_t	*tm_json_deserialize_check_now(const struct zbx_json_parse *jp)
791 {
792 	char		value[MAX_ID_LEN + 1];
793 	zbx_uint64_t	itemid;
794 
795 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_ITEMID, value, sizeof(value), NULL) ||
796 			SUCCEED != is_uint64(value, &itemid))
797 	{
798 		return NULL;
799 	}
800 
801 	return zbx_tm_check_now_create(itemid);
802 }
803 
804 /******************************************************************************
805  *                                                                            *
806  * Function: tm_json_deserialize_task                                         *
807  *                                                                            *
808  * Purpose: deserializes common task data from json data                      *
809  *                                                                            *
810  * Parameters: jp - [IN] the json data                                        *
811  *                                                                            *
812  * Return value: The deserialized task data or NULL if deserialization failed.*
813  *                                                                            *
814  ******************************************************************************/
tm_json_deserialize_task(const struct zbx_json_parse * jp)815 static zbx_tm_task_t	*tm_json_deserialize_task(const struct zbx_json_parse *jp)
816 {
817 	char	value[MAX_STRING_LEN];
818 	int	type, clock, ttl;
819 
820 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_TYPE, value, sizeof(value), NULL))
821 		return NULL;
822 
823 	ZBX_STR2UCHAR(type, value);
824 
825 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_CLOCK, value, sizeof(value), NULL))
826 		return NULL;
827 
828 	clock = atoi(value);
829 
830 	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_TTL, value, sizeof(value), NULL))
831 		return NULL;
832 
833 	ttl = atoi(value);
834 
835 	return zbx_tm_task_create(0, type, ZBX_TM_STATUS_NEW, clock, ttl, 0);
836 }
837 
838 /******************************************************************************
839  *                                                                            *
840  * Function: zbx_tm_json_deserialize_tasks                                    *
841  *                                                                            *
842  * Purpose: deserializes tasks from json data                                 *
843  *                                                                            *
844  * Parameters: jp    - [IN] the json data                                     *
845  *             tasks - [OUT] the deserialized tasks                           *
846  *                                                                            *
847  ******************************************************************************/
zbx_tm_json_deserialize_tasks(const struct zbx_json_parse * jp,zbx_vector_ptr_t * tasks)848 void	zbx_tm_json_deserialize_tasks(const struct zbx_json_parse *jp, zbx_vector_ptr_t *tasks)
849 {
850 	const char		*pnext = NULL;
851 	struct zbx_json_parse	jp_task;
852 
853 	while (NULL != (pnext = zbx_json_next(jp, pnext)))
854 	{
855 		zbx_tm_task_t	*task;
856 
857 		if (SUCCEED != zbx_json_brackets_open(pnext, &jp_task))
858 		{
859 			zabbix_log(LOG_LEVEL_DEBUG, "Cannot deserialize task record: %s", jp->start);
860 			continue;
861 		}
862 
863 		task = tm_json_deserialize_task(&jp_task);
864 
865 		if (NULL == task)
866 		{
867 			zabbix_log(LOG_LEVEL_DEBUG, "Cannot deserialize task at: %s", jp_task.start);
868 			continue;
869 		}
870 
871 		switch (task->type)
872 		{
873 			case ZBX_TM_TASK_REMOTE_COMMAND:
874 				task->data = tm_json_deserialize_remote_command(&jp_task);
875 				break;
876 			case ZBX_TM_TASK_REMOTE_COMMAND_RESULT:
877 				task->data = tm_json_deserialize_remote_command_result(&jp_task);
878 				break;
879 			case ZBX_TM_TASK_CHECK_NOW:
880 				task->data = tm_json_deserialize_check_now(&jp_task);
881 				break;
882 			default:
883 				THIS_SHOULD_NEVER_HAPPEN;
884 				break;
885 		}
886 
887 		if (NULL == task->data)
888 		{
889 			zabbix_log(LOG_LEVEL_DEBUG, "Cannot deserialize task data at: %s", jp_task.start);
890 			zbx_tm_task_free(task);
891 			continue;
892 		}
893 
894 		zbx_vector_ptr_append(tasks, task);
895 	}
896 }
897