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 "stats.h"
23 #include "log.h"
24 
25 #include <uvm/uvm_extern.h>
26 
get_cpu_num()27 static int	get_cpu_num()
28 {
29 #ifdef HAVE_FUNCTION_SYSCTL_HW_NCPU	/* NetBSD 3.1 i386; NetBSD 4.0 i386 */
30 	size_t	len;
31 	int	mib[] = {CTL_HW, HW_NCPU}, ncpu;
32 
33 	len = sizeof(ncpu);
34 
35 	if (-1 == sysctl(mib, 2, &ncpu, &len, NULL, 0))
36 		return -1;
37 
38 	return ncpu;
39 #else
40 	return -1;
41 #endif
42 }
43 
SYSTEM_CPU_NUM(AGENT_REQUEST * request,AGENT_RESULT * result)44 int	SYSTEM_CPU_NUM(AGENT_REQUEST *request, AGENT_RESULT *result)
45 {
46 	char	*tmp;
47 	int	cpu_num;
48 
49 	if (1 < request->nparam)
50 	{
51 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
52 		return SYSINFO_RET_FAIL;
53 	}
54 
55 	tmp = get_rparam(request, 0);
56 
57 	/* only "online" (default) for parameter "type" is supported */
58 	if (NULL != tmp && '\0' != *tmp && 0 != strcmp(tmp, "online"))
59 	{
60 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
61 		return SYSINFO_RET_FAIL;
62 	}
63 
64 	if (-1 == (cpu_num = get_cpu_num()))
65 	{
66 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain number of CPUs."));
67 		return SYSINFO_RET_FAIL;
68 	}
69 
70 	SET_UI64_RESULT(result, cpu_num);
71 
72 	return SYSINFO_RET_OK;
73 }
74 
SYSTEM_CPU_UTIL(AGENT_REQUEST * request,AGENT_RESULT * result)75 int	SYSTEM_CPU_UTIL(AGENT_REQUEST *request, AGENT_RESULT *result)
76 {
77 	char	*tmp;
78 	int	cpu_num, state, mode;
79 
80 	if (3 < request->nparam)
81 	{
82 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
83 		return SYSINFO_RET_FAIL;
84 	}
85 
86 	tmp = get_rparam(request, 0);
87 
88 	if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "all"))
89 		cpu_num = ZBX_CPUNUM_ALL;
90 	else if (SUCCEED != is_uint31_1(tmp, &cpu_num))
91 	{
92 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
93 		return SYSINFO_RET_FAIL;
94 	}
95 
96 	tmp = get_rparam(request, 1);
97 
98 	if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "user"))
99 		state = ZBX_CPU_STATE_USER;
100 	else if (0 == strcmp(tmp, "nice"))
101 		state = ZBX_CPU_STATE_NICE;
102 	else if (0 == strcmp(tmp, "system"))
103 		state = ZBX_CPU_STATE_SYSTEM;
104 	else if (0 == strcmp(tmp, "idle"))
105 		state = ZBX_CPU_STATE_IDLE;
106 	else
107 	{
108 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
109 		return SYSINFO_RET_FAIL;
110 	}
111 
112 	tmp = get_rparam(request, 2);
113 
114 	if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1"))
115 		mode = ZBX_AVG1;
116 	else if (0 == strcmp(tmp, "avg5"))
117 		mode = ZBX_AVG5;
118 	else if (0 == strcmp(tmp, "avg15"))
119 		mode = ZBX_AVG15;
120 	else
121 	{
122 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
123 		return SYSINFO_RET_FAIL;
124 	}
125 
126 	return get_cpustat(result, cpu_num, state, mode);
127 }
128 
SYSTEM_CPU_LOAD(AGENT_REQUEST * request,AGENT_RESULT * result)129 int	SYSTEM_CPU_LOAD(AGENT_REQUEST *request, AGENT_RESULT *result)
130 {
131 	char	*tmp;
132 	int	mode, per_cpu = 1, cpu_num;
133 	double	load[ZBX_AVG_COUNT], value;
134 
135 	if (2 < request->nparam)
136 	{
137 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
138 		return SYSINFO_RET_FAIL;
139 	}
140 
141 	tmp = get_rparam(request, 0);
142 
143 	if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "all"))
144 		per_cpu = 0;
145 	else if (0 != strcmp(tmp, "percpu"))
146 	{
147 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
148 		return SYSINFO_RET_FAIL;
149 	}
150 
151 	tmp = get_rparam(request, 1);
152 
153 	if (NULL == tmp || '\0' == *tmp || 0 == strcmp(tmp, "avg1"))
154 		mode = ZBX_AVG1;
155 	else if (0 == strcmp(tmp, "avg5"))
156 		mode = ZBX_AVG5;
157 	else if (0 == strcmp(tmp, "avg15"))
158 		mode = ZBX_AVG15;
159 	else
160 	{
161 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
162 		return SYSINFO_RET_FAIL;
163 	}
164 
165 	if (mode >= getloadavg(load, 3))
166 	{
167 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain load average: %s", zbx_strerror(errno)));
168 		return SYSINFO_RET_FAIL;
169 	}
170 
171 	value = load[mode];
172 
173 	if (1 == per_cpu)
174 	{
175 		if (0 >= (cpu_num = get_cpu_num()))
176 		{
177 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain number of CPUs."));
178 			return SYSINFO_RET_FAIL;
179 		}
180 		value /= cpu_num;
181 	}
182 
183 	SET_DBL_RESULT(result, value);
184 
185 	return SYSINFO_RET_OK;
186 }
187 
SYSTEM_CPU_SWITCHES(AGENT_REQUEST * request,AGENT_RESULT * result)188 int     SYSTEM_CPU_SWITCHES(AGENT_REQUEST *request, AGENT_RESULT *result)
189 {
190 	int			mib[] = {CTL_VM, VM_UVMEXP2};
191 	size_t			len;
192 	struct uvmexp_sysctl	v;
193 
194 	len = sizeof(struct uvmexp_sysctl);
195 
196 	if (0 != sysctl(mib, 2, &v, &len, NULL, 0))
197 	{
198 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
199 		return SYSINFO_RET_FAIL;
200 	}
201 
202 	SET_UI64_RESULT(result, v.swtch);
203 
204 	return SYSINFO_RET_OK;
205 }
206 
SYSTEM_CPU_INTR(AGENT_REQUEST * request,AGENT_RESULT * result)207 int     SYSTEM_CPU_INTR(AGENT_REQUEST *request, AGENT_RESULT *result)
208 {
209 	int			mib[] = {CTL_VM, VM_UVMEXP2};
210 	size_t			len;
211 	struct uvmexp_sysctl	v;
212 
213 	len = sizeof(struct uvmexp_sysctl);
214 
215 	if (0 != sysctl(mib, 2, &v, &len, NULL, 0))
216 	{
217 		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", zbx_strerror(errno)));
218 		return SYSINFO_RET_FAIL;
219 	}
220 
221 	SET_UI64_RESULT(result, v.intrs);
222 
223 	return SYSINFO_RET_OK;
224 }
225