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 
24 static u_int	pagesize = 0;
25 
26 #define ZBX_SYSCTLBYNAME(name, value)									\
27 													\
28 	len = sizeof(value);										\
29 	if (0 != sysctlbyname(name, &value, &len, NULL, 0))						\
30 	{												\
31 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain \"%s\" system parameter: %s",	\
32 				name, zbx_strerror(errno)));						\
33 		return SYSINFO_RET_FAIL;								\
34 	}
35 
VM_MEMORY_TOTAL(AGENT_RESULT * result)36 static int	VM_MEMORY_TOTAL(AGENT_RESULT *result)
37 {
38 	unsigned long	totalbytes;
39 	size_t		len;
40 
41 	ZBX_SYSCTLBYNAME("hw.physmem", totalbytes);
42 
43 	SET_UI64_RESULT(result, (zbx_uint64_t)totalbytes);
44 
45 	return SYSINFO_RET_OK;
46 }
47 
VM_MEMORY_ACTIVE(AGENT_RESULT * result)48 static int	VM_MEMORY_ACTIVE(AGENT_RESULT *result)
49 {
50 	u_int	activepages;
51 	size_t	len;
52 
53 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_active_count", activepages);
54 
55 	SET_UI64_RESULT(result, (zbx_uint64_t)activepages * pagesize);
56 
57 	return SYSINFO_RET_OK;
58 }
59 
VM_MEMORY_INACTIVE(AGENT_RESULT * result)60 static int	VM_MEMORY_INACTIVE(AGENT_RESULT *result)
61 {
62 	u_int	inactivepages;
63 	size_t	len;
64 
65 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_inactive_count", inactivepages);
66 
67 	SET_UI64_RESULT(result, (zbx_uint64_t)inactivepages * pagesize);
68 
69 	return SYSINFO_RET_OK;
70 }
71 
VM_MEMORY_WIRED(AGENT_RESULT * result)72 static int	VM_MEMORY_WIRED(AGENT_RESULT *result)
73 {
74 	u_int	wiredpages;
75 	size_t	len;
76 
77 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_wire_count", wiredpages);
78 
79 	SET_UI64_RESULT(result, (zbx_uint64_t)wiredpages * pagesize);
80 
81 	return SYSINFO_RET_OK;
82 }
83 
VM_MEMORY_CACHED(AGENT_RESULT * result)84 static int	VM_MEMORY_CACHED(AGENT_RESULT *result)
85 {
86 	u_int	cachedpages;
87 	size_t	len;
88 
89 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
90 
91 	SET_UI64_RESULT(result, (zbx_uint64_t)cachedpages * pagesize);
92 
93 	return SYSINFO_RET_OK;
94 }
95 
VM_MEMORY_FREE(AGENT_RESULT * result)96 static int	VM_MEMORY_FREE(AGENT_RESULT *result)
97 {
98 	u_int	freepages;
99 	size_t	len;
100 
101 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_free_count", freepages);
102 
103 	SET_UI64_RESULT(result, (zbx_uint64_t)freepages * pagesize);
104 
105 	return SYSINFO_RET_OK;
106 }
107 
VM_MEMORY_USED(AGENT_RESULT * result)108 static int	VM_MEMORY_USED(AGENT_RESULT *result)
109 {
110 	u_int	activepages, wiredpages, cachedpages;
111 	size_t	len;
112 
113 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_active_count", activepages);
114 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_wire_count", wiredpages);
115 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
116 
117 	SET_UI64_RESULT(result, (zbx_uint64_t)(activepages + wiredpages + cachedpages) * pagesize);
118 
119 	return SYSINFO_RET_OK;
120 }
121 
VM_MEMORY_PUSED(AGENT_RESULT * result)122 static int	VM_MEMORY_PUSED(AGENT_RESULT *result)
123 {
124 	u_int	activepages, wiredpages, cachedpages, totalpages;
125 	size_t	len;
126 
127 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_active_count", activepages);
128 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_wire_count", wiredpages);
129 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
130 
131 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_page_count", totalpages);
132 
133 	if (0 == totalpages)
134 	{
135 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero."));
136 		return SYSINFO_RET_FAIL;
137 	}
138 
139 	SET_DBL_RESULT(result, (activepages + wiredpages + cachedpages) / (double)totalpages * 100);
140 
141 	return SYSINFO_RET_OK;
142 }
143 
VM_MEMORY_AVAILABLE(AGENT_RESULT * result)144 static int	VM_MEMORY_AVAILABLE(AGENT_RESULT *result)
145 {
146 	u_int	inactivepages, cachedpages, freepages;
147 	size_t	len;
148 
149 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_inactive_count", inactivepages);
150 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
151 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_free_count", freepages);
152 
153 	SET_UI64_RESULT(result, (zbx_uint64_t)(inactivepages + cachedpages + freepages) * pagesize);
154 
155 	return SYSINFO_RET_OK;
156 }
157 
VM_MEMORY_PAVAILABLE(AGENT_RESULT * result)158 static int	VM_MEMORY_PAVAILABLE(AGENT_RESULT *result)
159 {
160 	u_int	inactivepages, cachedpages, freepages, totalpages;
161 	size_t	len;
162 
163 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_inactive_count", inactivepages);
164 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_cache_count", cachedpages);
165 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_free_count", freepages);
166 
167 	ZBX_SYSCTLBYNAME("vm.stats.vm.v_page_count", totalpages);
168 
169 	if (0 == totalpages)
170 	{
171 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero."));
172 		return SYSINFO_RET_FAIL;
173 	}
174 
175 	SET_DBL_RESULT(result, (inactivepages + cachedpages + freepages) / (double)totalpages * 100);
176 
177 	return SYSINFO_RET_OK;
178 }
179 
VM_MEMORY_BUFFERS(AGENT_RESULT * result)180 static int	VM_MEMORY_BUFFERS(AGENT_RESULT *result)
181 {
182 	u_int	bufspace;
183 	size_t	len;
184 
185 	ZBX_SYSCTLBYNAME("vfs.bufspace", bufspace);
186 
187 	SET_UI64_RESULT(result, bufspace);
188 
189 	return SYSINFO_RET_OK;
190 }
191 
VM_MEMORY_SHARED(AGENT_RESULT * result)192 static int	VM_MEMORY_SHARED(AGENT_RESULT *result)
193 {
194 	struct vmtotal	vm;
195 	size_t		len = sizeof(vm);
196 	int		mib[] = {CTL_VM, VM_METER};
197 
198 	if (0 != sysctl(mib, 2, &vm, &len, NULL, 0))
199 	{
200 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
201 		return SYSINFO_RET_FAIL;
202 	}
203 
204 	SET_UI64_RESULT(result, (zbx_uint64_t)(vm.t_vmshr + vm.t_rmshr) * pagesize);
205 
206 	return SYSINFO_RET_OK;
207 }
208 
VM_MEMORY_SIZE(AGENT_REQUEST * request,AGENT_RESULT * result)209 int     VM_MEMORY_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
210 {
211 	char	*mode;
212 	int	ret;
213 
214 	if (1 < request->nparam)
215 	{
216 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
217 		return SYSINFO_RET_FAIL;
218 	}
219 
220 	if (0 == pagesize)
221 	{
222 		size_t	len;
223 
224 		ZBX_SYSCTLBYNAME("vm.stats.vm.v_page_size", pagesize);
225 	}
226 
227 	mode = get_rparam(request, 0);
228 
229 	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
230 		ret = VM_MEMORY_TOTAL(result);
231 	else if (0 == strcmp(mode, "active"))
232 		ret = VM_MEMORY_ACTIVE(result);
233 	else if (0 == strcmp(mode, "inactive"))
234 		ret = VM_MEMORY_INACTIVE(result);
235 	else if (0 == strcmp(mode, "wired"))
236 		ret = VM_MEMORY_WIRED(result);
237 	else if (0 == strcmp(mode, "cached"))
238 		ret = VM_MEMORY_CACHED(result);
239 	else if (0 == strcmp(mode, "free"))
240 		ret = VM_MEMORY_FREE(result);
241 	else if (0 == strcmp(mode, "used"))
242 		ret = VM_MEMORY_USED(result);
243 	else if (0 == strcmp(mode, "pused"))
244 		ret = VM_MEMORY_PUSED(result);
245 	else if (0 == strcmp(mode, "available"))
246 		ret = VM_MEMORY_AVAILABLE(result);
247 	else if (0 == strcmp(mode, "pavailable"))
248 		ret = VM_MEMORY_PAVAILABLE(result);
249 	else if (0 == strcmp(mode, "buffers"))
250 		ret = VM_MEMORY_BUFFERS(result);
251 	else if (0 == strcmp(mode, "shared"))
252 		ret = VM_MEMORY_SHARED(result);
253 	else
254 	{
255 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
256 		ret = SYSINFO_RET_FAIL;
257 	}
258 
259 	return ret;
260 }
261