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 "log.h"
23
get_swap_size(zbx_uint64_t * total,zbx_uint64_t * free,zbx_uint64_t * used,double * pfree,double * pused,char ** error)24 static int get_swap_size(zbx_uint64_t *total, zbx_uint64_t *free, zbx_uint64_t *used, double *pfree, double *pused,
25 char **error)
26 {
27 int mib[2];
28 size_t len;
29 struct uvmexp v;
30
31 mib[0] = CTL_VM;
32 mib[1] = VM_UVMEXP;
33
34 len = sizeof(v);
35
36 if (0 != sysctl(mib, 2, &v, &len, NULL, 0))
37 {
38 *error = zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno));
39 return SYSINFO_RET_FAIL;
40 }
41
42 /* int pagesize; size of a page (PAGE_SIZE): must be power of 2 */
43 /* int swpages; number of PAGE_SIZE'ed swap pages */
44 /* int swpginuse; number of swap pages in use */
45
46 if (NULL != total)
47 *total = (zbx_uint64_t)v.swpages * v.pagesize;
48 if (NULL != free)
49 *free = (zbx_uint64_t)(v.swpages - v.swpginuse) * v.pagesize;
50 if (NULL != used)
51 *used = (zbx_uint64_t)v.swpginuse * v.pagesize;
52 if (NULL != pfree)
53 *pfree = 0 != v.swpages ? (double)(100.0 * (v.swpages - v.swpginuse)) / v.swpages : 100;
54 if (NULL != pused)
55 *pused = 0 != v.swpages ? (double)(100.0 * v.swpginuse) / v.swpages : 0;
56
57 return SYSINFO_RET_OK;
58 }
59
SYSTEM_SWAP_TOTAL(AGENT_RESULT * result)60 static int SYSTEM_SWAP_TOTAL(AGENT_RESULT *result)
61 {
62 zbx_uint64_t value;
63 char *error;
64
65 if (SYSINFO_RET_OK != get_swap_size(&value, NULL, NULL, NULL, NULL, &error))
66 {
67 SET_MSG_RESULT(result, error);
68 return SYSINFO_RET_FAIL;
69 }
70
71 SET_UI64_RESULT(result, value);
72
73 return SYSINFO_RET_OK;
74 }
75
SYSTEM_SWAP_FREE(AGENT_RESULT * result)76 static int SYSTEM_SWAP_FREE(AGENT_RESULT *result)
77 {
78 zbx_uint64_t value;
79 char *error;
80
81 if (SYSINFO_RET_OK != get_swap_size(NULL, &value, NULL, NULL, NULL, &error))
82 {
83 SET_MSG_RESULT(result, error);
84 return SYSINFO_RET_FAIL;
85 }
86
87 SET_UI64_RESULT(result, value);
88
89 return SYSINFO_RET_OK;
90 }
91
SYSTEM_SWAP_USED(AGENT_RESULT * result)92 static int SYSTEM_SWAP_USED(AGENT_RESULT *result)
93 {
94 zbx_uint64_t value;
95 char *error;
96
97 if (SYSINFO_RET_OK != get_swap_size(NULL, NULL, &value, NULL, NULL, &error))
98 {
99 SET_MSG_RESULT(result, error);
100 return SYSINFO_RET_FAIL;
101 }
102
103 SET_UI64_RESULT(result, value);
104
105 return SYSINFO_RET_OK;
106 }
107
SYSTEM_SWAP_PFREE(AGENT_RESULT * result)108 static int SYSTEM_SWAP_PFREE(AGENT_RESULT *result)
109 {
110 double value;
111 char *error;
112
113 if (SYSINFO_RET_OK != get_swap_size(NULL, NULL, NULL, &value, NULL, &error))
114 {
115 SET_MSG_RESULT(result, error);
116 return SYSINFO_RET_FAIL;
117 }
118
119 SET_DBL_RESULT(result, value);
120
121 return SYSINFO_RET_OK;
122 }
123
SYSTEM_SWAP_PUSED(AGENT_RESULT * result)124 static int SYSTEM_SWAP_PUSED(AGENT_RESULT *result)
125 {
126 double value;
127 char *error;
128
129 if (SYSINFO_RET_OK != get_swap_size(NULL, NULL, NULL, NULL, &value, &error))
130 {
131 SET_MSG_RESULT(result, error);
132 return SYSINFO_RET_FAIL;
133 }
134
135 SET_DBL_RESULT(result, value);
136
137 return SYSINFO_RET_OK;
138 }
139
SYSTEM_SWAP_SIZE(AGENT_REQUEST * request,AGENT_RESULT * result)140 int SYSTEM_SWAP_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
141 {
142 char *swapdev, *mode;
143 int ret;
144
145 if (2 < request->nparam)
146 {
147 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
148 return SYSINFO_RET_FAIL;
149 }
150
151 swapdev = get_rparam(request, 0);
152 mode = get_rparam(request, 1);
153
154 if (NULL != swapdev && '\0' != *swapdev && 0 != strcmp(swapdev, "all"))
155 {
156 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
157 return SYSINFO_RET_FAIL;
158 }
159
160 if (NULL == mode || *mode == '\0' || 0 == strcmp(mode, "free"))
161 {
162 ret = SYSTEM_SWAP_FREE(result);
163 }
164 else if (0 == strcmp(mode, "used"))
165 {
166 ret = SYSTEM_SWAP_USED(result);
167 }
168 else if (0 == strcmp(mode, "total"))
169 {
170 ret = SYSTEM_SWAP_TOTAL(result);
171 }
172 else if (0 == strcmp(mode, "pfree"))
173 {
174 ret = SYSTEM_SWAP_PFREE(result);
175 }
176 else if (0 == strcmp(mode, "pused"))
177 {
178 ret = SYSTEM_SWAP_PUSED(result);
179 }
180 else
181 {
182 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
183 return SYSINFO_RET_FAIL;
184 }
185
186 return ret;
187 }
188
get_swap_io(zbx_uint64_t * icount,zbx_uint64_t * ipages,zbx_uint64_t * ocount,zbx_uint64_t * opages,char ** error)189 static int get_swap_io(zbx_uint64_t *icount, zbx_uint64_t *ipages, zbx_uint64_t *ocount, zbx_uint64_t *opages,
190 char **error)
191 {
192 int mib[2];
193 size_t len;
194 struct uvmexp v;
195
196 mib[0] = CTL_VM;
197 mib[1] = VM_UVMEXP;
198
199 len = sizeof(v);
200
201 if (0 != sysctl(mib, 2, &v, &len, NULL, 0))
202 {
203 *error = zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno));
204 return SYSINFO_RET_FAIL;
205 }
206
207 /* int swapins; swapins */
208 /* int swapouts; swapouts */
209 /* int pgswapin; pages swapped in */
210 /* int pgswapout; pages swapped out */
211
212 #if OpenBSD < 201311 /* swapins and swapouts are not supported starting from OpenBSD 5.4 */
213 if (NULL != icount)
214 *icount = (zbx_uint64_t)v.swapins;
215 if (NULL != ocount)
216 *ocount = (zbx_uint64_t)v.swapouts;
217 #else
218 if (NULL != icount || NULL != ocount)
219 {
220 *error = zbx_dsprintf(NULL, "Not supported by the system starting from OpenBSD 5.4.");
221 return SYSINFO_RET_FAIL;
222 }
223 #endif
224 if (NULL != ipages)
225 *ipages = (zbx_uint64_t)v.pgswapin;
226 if (NULL != opages)
227 *opages = (zbx_uint64_t)v.pgswapout;
228
229 return SYSINFO_RET_OK;
230 }
231
SYSTEM_SWAP_IN(AGENT_REQUEST * request,AGENT_RESULT * result)232 int SYSTEM_SWAP_IN(AGENT_REQUEST *request, AGENT_RESULT *result)
233 {
234 int ret;
235 char *swapdev, *mode, *error;
236 zbx_uint64_t value;
237
238 if (2 < request->nparam)
239 {
240 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
241 return SYSINFO_RET_FAIL;
242 }
243
244 swapdev = get_rparam(request, 0);
245 mode = get_rparam(request, 1);
246
247 /* the only supported parameter */
248 if (NULL != swapdev && '\0' != *swapdev && 0 != strcmp(swapdev, "all"))
249 {
250 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
251 return SYSINFO_RET_FAIL;
252 }
253
254 /* default parameter */
255 if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "count"))
256 {
257 ret = get_swap_io(&value, NULL, NULL, NULL, &error);
258 }
259 else if (0 == strcmp(mode, "pages"))
260 {
261 ret = get_swap_io(NULL, &value, NULL, NULL, &error);
262 }
263 else
264 {
265 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
266 return SYSINFO_RET_FAIL;
267 }
268
269 if (SYSINFO_RET_OK == ret)
270 SET_UI64_RESULT(result, value);
271 else
272 SET_MSG_RESULT(result, error);
273
274 return ret;
275 }
276
SYSTEM_SWAP_OUT(AGENT_REQUEST * request,AGENT_RESULT * result)277 int SYSTEM_SWAP_OUT(AGENT_REQUEST *request, AGENT_RESULT *result)
278 {
279 int ret;
280 char *swapdev, *mode, *error;
281 zbx_uint64_t value;
282
283 if (2 < request->nparam)
284 {
285 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
286 return SYSINFO_RET_FAIL;
287 }
288
289 swapdev = get_rparam(request, 0);
290 mode = get_rparam(request, 1);
291
292 /* the only supported parameter */
293 if (NULL != swapdev && '\0' != *swapdev && 0 != strcmp(swapdev, "all"))
294 {
295 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
296 return SYSINFO_RET_FAIL;
297 }
298
299 /* default parameter */
300 if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "count"))
301 {
302 ret = get_swap_io(NULL, NULL, &value, NULL, &error);
303 }
304 else if (0 == strcmp(mode, "pages"))
305 {
306 ret = get_swap_io(NULL, NULL, NULL, &value, &error);
307 }
308 else
309 {
310 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
311 return SYSINFO_RET_FAIL;
312 }
313
314 if (SYSINFO_RET_OK == ret)
315 SET_UI64_RESULT(result, value);
316 else
317 SET_MSG_RESULT(result, error);
318
319
320 return ret;
321 }
322