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 vm_size_t	pagesize = 0;
25 
26 static struct vm_statistics	vm;
27 static mach_msg_type_number_t	count;
28 
29 #define ZBX_HOST_STATISTICS(value)										\
30 														\
31 	count = HOST_VM_INFO_COUNT;										\
32 	if (KERN_SUCCESS != host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&value, &count))	\
33 	{													\
34 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain host statistics."));			\
35 		return SYSINFO_RET_FAIL;									\
36 	}
37 
38 static int		mib[] = {CTL_HW, HW_MEMSIZE};
39 static size_t		len;
40 static zbx_uint64_t	memsize;
41 
42 #define ZBX_SYSCTL(value)											\
43 														\
44 	len = sizeof(value);											\
45 	if (0 != sysctl(mib, 2, &value, &len, NULL, 0))								\
46 	{													\
47 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s",		\
48 				zbx_strerror(errno)));								\
49 		return SYSINFO_RET_FAIL;									\
50 	}
51 
VM_MEMORY_TOTAL(AGENT_RESULT * result)52 static int	VM_MEMORY_TOTAL(AGENT_RESULT *result)
53 {
54 	ZBX_SYSCTL(memsize);
55 
56 	SET_UI64_RESULT(result, memsize);
57 
58 	return SYSINFO_RET_OK;
59 }
60 
VM_MEMORY_ACTIVE(AGENT_RESULT * result)61 static int	VM_MEMORY_ACTIVE(AGENT_RESULT *result)
62 {
63 	ZBX_HOST_STATISTICS(vm);
64 
65 	SET_UI64_RESULT(result, (zbx_uint64_t)vm.active_count * pagesize);
66 
67 	return SYSINFO_RET_OK;
68 }
69 
VM_MEMORY_INACTIVE(AGENT_RESULT * result)70 static int	VM_MEMORY_INACTIVE(AGENT_RESULT *result)
71 {
72 	ZBX_HOST_STATISTICS(vm);
73 
74 	SET_UI64_RESULT(result, (zbx_uint64_t)vm.inactive_count * pagesize);
75 
76 	return SYSINFO_RET_OK;
77 }
78 
VM_MEMORY_WIRED(AGENT_RESULT * result)79 static int	VM_MEMORY_WIRED(AGENT_RESULT *result)
80 {
81 	ZBX_HOST_STATISTICS(vm);
82 
83 	SET_UI64_RESULT(result, (zbx_uint64_t)vm.wire_count * pagesize);
84 
85 	return SYSINFO_RET_OK;
86 }
87 
VM_MEMORY_FREE(AGENT_RESULT * result)88 static int	VM_MEMORY_FREE(AGENT_RESULT *result)
89 {
90 	ZBX_HOST_STATISTICS(vm);
91 
92 	SET_UI64_RESULT(result, (zbx_uint64_t)vm.free_count * pagesize);
93 
94 	return SYSINFO_RET_OK;
95 }
96 
VM_MEMORY_USED(AGENT_RESULT * result)97 static int	VM_MEMORY_USED(AGENT_RESULT *result)
98 {
99 	ZBX_HOST_STATISTICS(vm);
100 
101 	SET_UI64_RESULT(result, (zbx_uint64_t)(vm.active_count + vm.wire_count) * pagesize);
102 
103 	return SYSINFO_RET_OK;
104 }
105 
VM_MEMORY_PUSED(AGENT_RESULT * result)106 static int	VM_MEMORY_PUSED(AGENT_RESULT *result)
107 {
108 	zbx_uint64_t	used;
109 
110 	ZBX_SYSCTL(memsize);
111 
112 	if (0 == memsize)
113 	{
114 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero."));
115 		return SYSINFO_RET_FAIL;
116 	}
117 
118 	ZBX_HOST_STATISTICS(vm);
119 
120 	used = (zbx_uint64_t)(vm.active_count + vm.wire_count) * pagesize;
121 
122 	SET_DBL_RESULT(result, used / (double)memsize * 100);
123 
124 	return SYSINFO_RET_OK;
125 }
126 
VM_MEMORY_AVAILABLE(AGENT_RESULT * result)127 static int	VM_MEMORY_AVAILABLE(AGENT_RESULT *result)
128 {
129 	ZBX_HOST_STATISTICS(vm);
130 
131 	SET_UI64_RESULT(result, (zbx_uint64_t)(vm.inactive_count + vm.free_count) * pagesize);
132 
133 	return SYSINFO_RET_OK;
134 }
135 
VM_MEMORY_PAVAILABLE(AGENT_RESULT * result)136 static int	VM_MEMORY_PAVAILABLE(AGENT_RESULT *result)
137 {
138 	zbx_uint64_t	available;
139 
140 	ZBX_SYSCTL(memsize);
141 
142 	if (0 == memsize)
143 	{
144 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot calculate percentage because total is zero."));
145 		return SYSINFO_RET_FAIL;
146 	}
147 
148 	ZBX_HOST_STATISTICS(vm);
149 
150 	available = (zbx_uint64_t)(vm.inactive_count + vm.free_count) * pagesize;
151 
152 	SET_DBL_RESULT(result, available / (double)memsize * 100);
153 
154 	return SYSINFO_RET_OK;
155 }
156 
VM_MEMORY_SIZE(AGENT_REQUEST * request,AGENT_RESULT * result)157 int	VM_MEMORY_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
158 {
159 	char	*mode;
160 	int	ret = SYSINFO_RET_FAIL;
161 
162 	if (1 < request->nparam)
163 	{
164 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
165 		return SYSINFO_RET_FAIL;
166 	}
167 
168 	if (0 == pagesize)
169 	{
170 		if (KERN_SUCCESS != host_page_size(mach_host_self(), &pagesize))
171 		{
172 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain host page size."));
173 			return SYSINFO_RET_FAIL;
174 		}
175 	}
176 
177 	mode = get_rparam(request, 0);
178 
179 	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
180 		ret = VM_MEMORY_TOTAL(result);
181 	else if (0 == strcmp(mode, "active"))
182 		ret = VM_MEMORY_ACTIVE(result);
183 	else if (0 == strcmp(mode, "inactive"))
184 		ret = VM_MEMORY_INACTIVE(result);
185 	else if (0 == strcmp(mode, "wired"))
186 		ret = VM_MEMORY_WIRED(result);
187 	else if (0 == strcmp(mode, "free"))
188 		ret = VM_MEMORY_FREE(result);
189 	else if (0 == strcmp(mode, "used"))
190 		ret = VM_MEMORY_USED(result);
191 	else if (0 == strcmp(mode, "pused"))
192 		ret = VM_MEMORY_PUSED(result);
193 	else if (0 == strcmp(mode, "available"))
194 		ret = VM_MEMORY_AVAILABLE(result);
195 	else if (0 == strcmp(mode, "pavailable"))
196 		ret = VM_MEMORY_PAVAILABLE(result);
197 	else
198 	{
199 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
200 		return SYSINFO_RET_FAIL;
201 	}
202 
203 	return ret;
204 }
205