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 "comms.h"
22 #include "zbxjson.h"
23 #include "log.h"
24
25 /******************************************************************************
26 * *
27 * Function: zbx_send_response *
28 * *
29 * Purpose: send json SUCCEED or FAIL to socket along with an info message *
30 * *
31 * Parameters: sock - [IN] socket descriptor *
32 * result - [IN] SUCCEED or FAIL *
33 * info - [IN] info message (optional) *
34 * version - [IN] the version data (optional) *
35 * protocol - [IN] the transport protocol *
36 * timeout - [IN] timeout for this operation *
37 * *
38 * Return value: SUCCEED - data successfully transmitted *
39 * NETWORK_ERROR - network related error occurred *
40 * *
41 * Author: Alexander Vladishev, Alexei Vladishev *
42 * *
43 * Comments: *
44 * *
45 ******************************************************************************/
zbx_send_response_ext(zbx_socket_t * sock,int result,const char * info,const char * version,int protocol,int timeout)46 int zbx_send_response_ext(zbx_socket_t *sock, int result, const char *info, const char *version, int protocol,
47 int timeout)
48 {
49 struct zbx_json json;
50 const char *resp;
51 int ret = SUCCEED;
52
53 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
54
55 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
56
57 resp = SUCCEED == result ? ZBX_PROTO_VALUE_SUCCESS : ZBX_PROTO_VALUE_FAILED;
58
59 zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, resp, ZBX_JSON_TYPE_STRING);
60
61 if (NULL != info && '\0' != *info)
62 zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, info, ZBX_JSON_TYPE_STRING);
63
64 if (NULL != version)
65 zbx_json_addstring(&json, ZBX_PROTO_TAG_VERSION, version, ZBX_JSON_TYPE_STRING);
66
67 zabbix_log(LOG_LEVEL_DEBUG, "%s() '%s'", __func__, json.buffer);
68
69 if (FAIL == (ret = zbx_tcp_send_ext(sock, json.buffer, strlen(json.buffer), 0, protocol, timeout)))
70 {
71 zabbix_log(LOG_LEVEL_DEBUG, "Error sending result back: %s", zbx_socket_strerror());
72 ret = NETWORK_ERROR;
73 }
74
75 zbx_json_free(&json);
76
77 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
78
79 return ret;
80 }
81
82 /******************************************************************************
83 * *
84 * Function: zbx_recv_response *
85 * *
86 * Purpose: read a response message (in JSON format) from socket, optionally *
87 * extract "info" value. *
88 * *
89 * Parameters: sock - [IN] socket descriptor *
90 * timeout - [IN] timeout for this operation *
91 * error - [OUT] pointer to error message *
92 * *
93 * Return value: SUCCEED - "response":"success" successfully retrieved *
94 * FAIL - otherwise *
95 * Comments: *
96 * Allocates memory. *
97 * *
98 * If an error occurs, the function allocates dynamic memory for an error *
99 * message and writes its address into location pointed to by "error" *
100 * parameter. *
101 * *
102 * When the "info" value is present in the response message then function *
103 * copies the "info" value into the "error" buffer as additional *
104 * information *
105 * *
106 * IMPORTANT: it is a responsibility of the caller to release the *
107 * "error" memory ! *
108 * *
109 ******************************************************************************/
zbx_recv_response(zbx_socket_t * sock,int timeout,char ** error)110 int zbx_recv_response(zbx_socket_t *sock, int timeout, char **error)
111 {
112 struct zbx_json_parse jp;
113 char value[16];
114 int ret = FAIL;
115
116 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
117
118 if (SUCCEED != zbx_tcp_recv_to(sock, timeout))
119 {
120 /* since we have successfully sent data earlier, we assume the other */
121 /* side is just too busy processing our data if there is no response */
122 *error = zbx_strdup(*error, zbx_socket_strerror());
123 goto out;
124 }
125
126 zabbix_log(LOG_LEVEL_DEBUG, "%s() '%s'", __func__, sock->buffer);
127
128 /* deal with empty string here because zbx_json_open() does not produce an error message in this case */
129 if ('\0' == *sock->buffer)
130 {
131 *error = zbx_strdup(*error, "empty string received");
132 goto out;
133 }
134
135 if (SUCCEED != zbx_json_open(sock->buffer, &jp))
136 {
137 *error = zbx_strdup(*error, zbx_json_strerror());
138 goto out;
139 }
140
141 if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_RESPONSE, value, sizeof(value), NULL))
142 {
143 *error = zbx_strdup(*error, "no \"" ZBX_PROTO_TAG_RESPONSE "\" tag");
144 goto out;
145 }
146
147 if (0 != strcmp(value, ZBX_PROTO_VALUE_SUCCESS))
148 {
149 char *info = NULL;
150 size_t info_alloc = 0;
151
152 if (SUCCEED == zbx_json_value_by_name_dyn(&jp, ZBX_PROTO_TAG_INFO, &info, &info_alloc, NULL))
153 *error = zbx_strdup(*error, info);
154 else
155 *error = zbx_dsprintf(*error, "negative response \"%s\"", value);
156 zbx_free(info);
157 goto out;
158 }
159
160 ret = SUCCEED;
161 out:
162 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
163
164 return ret;
165 }
166