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
24 #include "zabbix_stats.h"
25
26 /******************************************************************************
27 * *
28 * Function: check_response *
29 * *
30 * Purpose: Check whether JSON response is "success" or "failed" *
31 * *
32 * Parameters: response - [IN] the request *
33 * result - [OUT] check result *
34 * *
35 * Return value: SUCCEED - processed successfully *
36 * FAIL - an error occurred *
37 * *
38 ******************************************************************************/
check_response(const char * response,AGENT_RESULT * result)39 static int check_response(const char *response, AGENT_RESULT *result)
40 {
41 struct zbx_json_parse jp;
42 char buffer[MAX_STRING_LEN];
43
44 if (SUCCEED != zbx_json_open(response, &jp))
45 {
46 SET_MSG_RESULT(result, zbx_strdup(NULL, "Value should be a JSON object."));
47 return FAIL;
48 }
49
50 if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_RESPONSE, buffer, sizeof(buffer), NULL))
51 {
52 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot find tag: %s.", ZBX_PROTO_TAG_RESPONSE));
53 return FAIL;
54 }
55
56 if (0 != strcmp(buffer, ZBX_PROTO_VALUE_SUCCESS))
57 {
58 if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_INFO, buffer, sizeof(buffer), NULL))
59 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot find tag: %s.", ZBX_PROTO_TAG_INFO));
60 else
61 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain internal statistics: %s", buffer));
62
63 return FAIL;
64 }
65
66 return SUCCEED;
67 }
68
69 /******************************************************************************
70 * *
71 * Function: get_remote_zabbix_stats *
72 * *
73 * Purpose: send Zabbix stats request and receive the result data *
74 * *
75 * Parameters: json - [IN] the request *
76 * ip - [IN] external Zabbix instance hostname *
77 * port - [IN] external Zabbix instance port *
78 * result - [OUT] check result *
79 * *
80 ******************************************************************************/
get_remote_zabbix_stats(const struct zbx_json * json,const char * ip,unsigned short port,AGENT_RESULT * result)81 static void get_remote_zabbix_stats(const struct zbx_json *json, const char *ip, unsigned short port,
82 AGENT_RESULT *result)
83 {
84 zbx_socket_t s;
85
86 if (SUCCEED == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, ip, port, CONFIG_TIMEOUT, ZBX_TCP_SEC_UNENCRYPTED,
87 NULL, NULL))
88 {
89 if (SUCCEED == zbx_tcp_send(&s, json->buffer))
90 {
91 if (SUCCEED == zbx_tcp_recv(&s) && NULL != s.buffer)
92 {
93 if ('\0' == *s.buffer)
94 {
95 SET_MSG_RESULT(result, zbx_strdup(NULL,
96 "Cannot obtain internal statistics: received empty response."));
97 }
98 else if (SUCCEED == check_response(s.buffer, result))
99 set_result_type(result, ITEM_VALUE_TYPE_TEXT, s.buffer);
100 }
101 else
102 {
103 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain internal statistics: %s",
104 zbx_socket_strerror()));
105 }
106 }
107 else
108 {
109 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain internal statistics: %s",
110 zbx_socket_strerror()));
111 }
112
113 zbx_tcp_close(&s);
114 }
115 else
116 {
117 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain internal statistics: %s",
118 zbx_socket_strerror()));
119 }
120 }
121
122 /******************************************************************************
123 * *
124 * Function: zbx_get_remote_zabbix_stats *
125 * *
126 * Purpose: create Zabbix stats request *
127 * *
128 * Parameters: ip - [IN] external Zabbix instance hostname *
129 * port - [IN] external Zabbix instance port *
130 * result - [OUT] check result *
131 * *
132 * Return value: SUCCEED - processed successfully *
133 * FAIL - an error occurred *
134 * *
135 ******************************************************************************/
zbx_get_remote_zabbix_stats(const char * ip,unsigned short port,AGENT_RESULT * result)136 int zbx_get_remote_zabbix_stats(const char *ip, unsigned short port, AGENT_RESULT *result)
137 {
138 struct zbx_json json;
139
140 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
141 zbx_json_addstring(&json, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_ZABBIX_STATS, ZBX_JSON_TYPE_STRING);
142
143 get_remote_zabbix_stats(&json, ip, port, result);
144
145 zbx_json_free(&json);
146
147 return 0 == ISSET_MSG(result) ? SUCCEED : FAIL;
148 }
149
150 /******************************************************************************
151 * *
152 * Function: zbx_get_remote_zabbix_stats_queue *
153 * *
154 * Purpose: create Zabbix stats queue request *
155 * *
156 * Parameters: ip - [IN] external Zabbix instance hostname *
157 * port - [IN] external Zabbix instance port *
158 * from - [IN] lower limit for delay *
159 * to - [IN] upper limit for delay *
160 * result - [OUT] check result *
161 * *
162 * Return value: SUCCEED - processed successfully *
163 * FAIL - an error occurred *
164 * *
165 ******************************************************************************/
zbx_get_remote_zabbix_stats_queue(const char * ip,unsigned short port,const char * from,const char * to,AGENT_RESULT * result)166 int zbx_get_remote_zabbix_stats_queue(const char *ip, unsigned short port, const char *from, const char *to,
167 AGENT_RESULT *result)
168 {
169 struct zbx_json json;
170
171 zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
172 zbx_json_addstring(&json, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_ZABBIX_STATS, ZBX_JSON_TYPE_STRING);
173 zbx_json_addstring(&json, ZBX_PROTO_TAG_TYPE, ZBX_PROTO_VALUE_ZABBIX_STATS_QUEUE, ZBX_JSON_TYPE_STRING);
174
175 zbx_json_addobject(&json, ZBX_PROTO_TAG_PARAMS);
176
177 if (NULL != from && '\0' != *from)
178 zbx_json_addstring(&json, ZBX_PROTO_TAG_FROM, from, ZBX_JSON_TYPE_STRING);
179 if (NULL != to && '\0' != *to)
180 zbx_json_addstring(&json, ZBX_PROTO_TAG_TO, to, ZBX_JSON_TYPE_STRING);
181
182 zbx_json_close(&json);
183
184 get_remote_zabbix_stats(&json, ip, port, result);
185
186 zbx_json_free(&json);
187
188 return 0 == ISSET_MSG(result) ? SUCCEED : FAIL;
189 }
190
ZABBIX_STATS(AGENT_REQUEST * request,AGENT_RESULT * result)191 int ZABBIX_STATS(AGENT_REQUEST *request, AGENT_RESULT *result)
192 {
193 const char *ip_str, *port_str, *queue_str;
194 unsigned short port_number;
195
196 if (5 < request->nparam)
197 {
198 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
199 return SYSINFO_RET_FAIL;
200 }
201
202 if (NULL == (ip_str = get_rparam(request, 0)) || '\0' == *ip_str)
203 ip_str = "127.0.0.1";
204
205 if (NULL == (port_str = get_rparam(request, 1)) || '\0' == *port_str)
206 {
207 port_number = ZBX_DEFAULT_SERVER_PORT;
208 }
209 else if (SUCCEED != is_ushort(port_str, &port_number))
210 {
211 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
212 return SYSINFO_RET_FAIL;
213 }
214
215 queue_str = get_rparam(request, 2);
216
217 if (3 > request->nparam)
218 {
219 if (SUCCEED != zbx_get_remote_zabbix_stats(ip_str, port_number, result))
220 return SYSINFO_RET_FAIL;
221 }
222 else if (NULL != queue_str && 0 == strcmp(queue_str, ZBX_PROTO_VALUE_ZABBIX_STATS_QUEUE))
223 {
224 if (SUCCEED != zbx_get_remote_zabbix_stats_queue(ip_str, port_number, get_rparam(request, 3),
225 get_rparam(request, 4), result))
226 {
227 return SYSINFO_RET_FAIL;
228 }
229 }
230 else
231 {
232 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
233 return SYSINFO_RET_FAIL;
234 }
235
236 return SYSINFO_RET_OK;
237 }
238