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 "sysinfo.h"
22 #include "../common/common.h"
23 #include "zbxjson.h"
24 #include "log.h"
25
26 static struct ifmibdata ifmd;
27
get_ifmib_general(const char * if_name,char ** error)28 static int get_ifmib_general(const char *if_name, char **error)
29 {
30 int mib[6], ifcount;
31 size_t len;
32
33 if (NULL == if_name || '\0' == *if_name)
34 {
35 *error = zbx_strdup(NULL, "Network interface name cannot be empty.");
36 return FAIL;
37 }
38
39 mib[0] = CTL_NET;
40 mib[1] = PF_LINK;
41 mib[2] = NETLINK_GENERIC;
42 mib[3] = IFMIB_SYSTEM;
43 mib[4] = IFMIB_IFCOUNT;
44
45 len = sizeof(ifcount);
46
47 if (-1 == sysctl(mib, 5, &ifcount, &len, NULL, 0))
48 {
49 *error = zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno));
50 return FAIL;
51 }
52
53 mib[3] = IFMIB_IFDATA;
54 mib[5] = IFDATA_GENERAL;
55
56 len = sizeof(ifmd);
57
58 for (mib[4] = 1; mib[4] <= ifcount; mib[4]++)
59 {
60 if (-1 == sysctl(mib, 6, &ifmd, &len, NULL, 0))
61 {
62 if (ENOENT == errno)
63 continue;
64
65 break;
66 }
67
68 if (0 == strcmp(ifmd.ifmd_name, if_name))
69 return SUCCEED;
70 }
71
72 *error = zbx_strdup(NULL, "Cannot find information for this network interface.");
73
74 return FAIL;
75 }
76
NET_IF_IN(AGENT_REQUEST * request,AGENT_RESULT * result)77 int NET_IF_IN(AGENT_REQUEST *request, AGENT_RESULT *result)
78 {
79 char *if_name, *mode, *error;
80
81 if (2 < request->nparam)
82 {
83 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
84 return SYSINFO_RET_FAIL;
85 }
86
87 if_name = get_rparam(request, 0);
88 mode = get_rparam(request, 1);
89
90 if (FAIL == get_ifmib_general(if_name,&error))
91 {
92 SET_MSG_RESULT(result, error);
93 return SYSINFO_RET_FAIL;
94 }
95
96 if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "bytes")) /* default parameter */
97 SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_ibytes);
98 else if (0 == strcmp(mode, "packets"))
99 SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_ipackets);
100 else if (0 == strcmp(mode, "errors"))
101 SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_ierrors);
102 else if (0 == strcmp(mode, "dropped"))
103 SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_iqdrops);
104 else
105 {
106 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
107 return SYSINFO_RET_FAIL;
108 }
109
110 return SYSINFO_RET_OK;
111 }
112
NET_IF_OUT(AGENT_REQUEST * request,AGENT_RESULT * result)113 int NET_IF_OUT(AGENT_REQUEST *request, AGENT_RESULT *result)
114 {
115 char *if_name, *mode, *error;
116
117 if (2 < request->nparam)
118 {
119 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
120 return SYSINFO_RET_FAIL;
121 }
122
123 if_name = get_rparam(request, 0);
124 mode = get_rparam(request, 1);
125
126 if (FAIL == get_ifmib_general(if_name, &error))
127 {
128 SET_MSG_RESULT(result, error);
129 return SYSINFO_RET_FAIL;
130 }
131
132 if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "bytes")) /* default parameter */
133 SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_obytes);
134 else if (0 == strcmp(mode, "packets"))
135 SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_opackets);
136 else if (0 == strcmp(mode, "errors"))
137 SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_oerrors);
138 else
139 {
140 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
141 return SYSINFO_RET_FAIL;
142 }
143
144 return SYSINFO_RET_OK;
145 }
146
NET_IF_TOTAL(AGENT_REQUEST * request,AGENT_RESULT * result)147 int NET_IF_TOTAL(AGENT_REQUEST *request, AGENT_RESULT *result)
148 {
149 char *if_name, *mode, *error;
150
151 if (2 < request->nparam)
152 {
153 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
154 return SYSINFO_RET_FAIL;
155 }
156
157 if_name = get_rparam(request, 0);
158 mode = get_rparam(request, 1);
159
160 if (FAIL == get_ifmib_general(if_name, &error))
161 {
162 SET_MSG_RESULT(result, error);
163 return SYSINFO_RET_FAIL;
164 }
165
166 if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "bytes")) /* default parameter */
167 SET_UI64_RESULT(result, (zbx_uint64_t)ifmd.ifmd_data.ifi_ibytes + ifmd.ifmd_data.ifi_obytes);
168 else if (0 == strcmp(mode, "packets"))
169 SET_UI64_RESULT(result, (zbx_uint64_t)ifmd.ifmd_data.ifi_ipackets + ifmd.ifmd_data.ifi_opackets);
170 else if (0 == strcmp(mode, "errors"))
171 SET_UI64_RESULT(result, (zbx_uint64_t)ifmd.ifmd_data.ifi_ierrors + ifmd.ifmd_data.ifi_oerrors);
172 else
173 {
174 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
175 return SYSINFO_RET_FAIL;
176 }
177
178 return SYSINFO_RET_OK;
179 }
180
NET_TCP_LISTEN(AGENT_REQUEST * request,AGENT_RESULT * result)181 int NET_TCP_LISTEN(AGENT_REQUEST *request, AGENT_RESULT *result)
182 {
183 char *port_str, command[64];
184 unsigned short port;
185 int res;
186
187 if (1 < request->nparam)
188 {
189 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
190 return SYSINFO_RET_FAIL;
191 }
192
193 port_str = get_rparam(request, 0);
194
195 if (NULL == port_str || SUCCEED != is_ushort(port_str, &port))
196 {
197 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
198 return SYSINFO_RET_FAIL;
199 }
200
201 zbx_snprintf(command, sizeof(command), "netstat -an | grep '^tcp.*\\.%hu[^.].*LISTEN' | wc -l", port);
202
203 if (SYSINFO_RET_FAIL == (res = EXECUTE_INT(command, result)))
204 return res;
205
206 if (1 < result->ui64)
207 result->ui64 = 1;
208
209 return res;
210 }
211
NET_UDP_LISTEN(AGENT_REQUEST * request,AGENT_RESULT * result)212 int NET_UDP_LISTEN(AGENT_REQUEST *request, AGENT_RESULT *result)
213 {
214 char *port_str, command[64];
215 unsigned short port;
216 int res;
217
218 if (1 < request->nparam)
219 {
220 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
221 return SYSINFO_RET_FAIL;
222 }
223
224 port_str = get_rparam(request, 0);
225
226 if (NULL == port_str || SUCCEED != is_ushort(port_str, &port))
227 {
228 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
229 return SYSINFO_RET_FAIL;
230 }
231
232 zbx_snprintf(command, sizeof(command), "netstat -an | grep '^udp.*\\.%hu[^.].*\\*\\.\\*' | wc -l", port);
233
234 if (SYSINFO_RET_FAIL == (res = EXECUTE_INT(command, result)))
235 return res;
236
237 if (1 < result->ui64)
238 result->ui64 = 1;
239
240 return res;
241 }
242
NET_IF_COLLISIONS(AGENT_REQUEST * request,AGENT_RESULT * result)243 int NET_IF_COLLISIONS(AGENT_REQUEST *request, AGENT_RESULT *result)
244 {
245 char *if_name, *error;
246
247 if (1 < request->nparam)
248 {
249 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
250 return SYSINFO_RET_FAIL;
251 }
252
253 if_name = get_rparam(request, 0);
254
255 if (FAIL == get_ifmib_general(if_name, &error))
256 {
257 SET_MSG_RESULT(result, error);
258 return SYSINFO_RET_FAIL;
259 }
260
261 SET_UI64_RESULT(result, ifmd.ifmd_data.ifi_collisions);
262
263 return SYSINFO_RET_OK;
264 }
265
NET_IF_DISCOVERY(AGENT_REQUEST * request,AGENT_RESULT * result)266 int NET_IF_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result)
267 {
268 int i;
269 struct zbx_json j;
270 struct if_nameindex *interfaces;
271
272 if (NULL == (interfaces = if_nameindex()))
273 {
274 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
275 return SYSINFO_RET_FAIL;
276 }
277
278 zbx_json_initarray(&j, ZBX_JSON_STAT_BUF_LEN);
279
280 for (i = 0; 0 != interfaces[i].if_index; i++)
281 {
282 zbx_json_addobject(&j, NULL);
283 zbx_json_addstring(&j, "{#IFNAME}", interfaces[i].if_name, ZBX_JSON_TYPE_STRING);
284 zbx_json_close(&j);
285 }
286
287 zbx_json_close(&j);
288
289 SET_STR_RESULT(result, strdup(j.buffer));
290
291 zbx_json_free(&j);
292
293 if_freenameindex(interfaces);
294
295 return SYSINFO_RET_OK;
296 }
297