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_diskstat(const char * devname,zbx_uint64_t * dstat)24 int	get_diskstat(const char *devname, zbx_uint64_t *dstat)
25 {
26 	return FAIL;
27 }
28 
get_disk_stats(const char * devname,zbx_uint64_t * rbytes,zbx_uint64_t * wbytes,zbx_uint64_t * roper,zbx_uint64_t * woper,char ** error)29 static int	get_disk_stats(const char *devname, zbx_uint64_t *rbytes, zbx_uint64_t *wbytes, zbx_uint64_t *roper,
30 		zbx_uint64_t *woper, char **error)
31 {
32 	int			ret = SYSINFO_RET_FAIL, mib[2], i, drive_count;
33 	size_t			len;
34 	struct diskstats	*stats;
35 
36 	mib[0] = CTL_HW;
37 	mib[1] = HW_DISKCOUNT;
38 
39 	len = sizeof(drive_count);
40 
41 	if (0 != sysctl(mib, 2, &drive_count, &len, NULL, 0))
42 	{
43 		*error = zbx_dsprintf(NULL, "Cannot obtain number of disks: %s", zbx_strerror(errno));
44 		return SYSINFO_RET_FAIL;
45 	}
46 
47 	len = drive_count * sizeof(struct diskstats);
48 
49 	stats = zbx_calloc(NULL, drive_count, len);
50 
51 	mib[0] = CTL_HW;
52 	mib[1] = HW_DISKSTATS;
53 
54 	if (NULL != rbytes)
55 		*rbytes = 0;
56 	if (NULL != wbytes)
57 		*wbytes = 0;
58 	if (NULL != roper)
59 		*roper = 0;
60 	if (NULL != woper)
61 		*woper = 0;
62 
63 	if (0 != sysctl(mib, 2, stats, &len, NULL, 0))
64 	{
65 		zbx_free(stats);
66 		*error = zbx_dsprintf(NULL, "Cannot obtain disk information: %s", zbx_strerror(errno));
67 		return SYSINFO_RET_FAIL;
68 	}
69 
70 	for (i = 0; i < drive_count; i++)
71 	{
72 		if (NULL == devname || '\0' == *devname || 0 == strcmp(devname, "all") ||
73 				0 == strcmp(devname, stats[i].ds_name))
74 		{
75 			if (NULL != rbytes)
76 				*rbytes += stats[i].ds_rbytes;
77 			if (NULL != wbytes)
78 				*wbytes += stats[i].ds_wbytes;
79 			if (NULL != roper)
80 				*roper += stats[i].ds_rxfer;
81 			if (NULL != woper)
82 				*woper += stats[i].ds_wxfer;
83 
84 			ret = SYSINFO_RET_OK;
85 		}
86 	}
87 
88 	zbx_free(stats);
89 
90 	if (SYSINFO_RET_FAIL == ret)
91 	{
92 		*error = zbx_strdup(NULL, "Cannot find information for this disk device.");
93 		return SYSINFO_RET_FAIL;
94 	}
95 
96 	return ret;
97 }
98 
VFS_DEV_READ_BYTES(const char * devname,AGENT_RESULT * result)99 static int	VFS_DEV_READ_BYTES(const char *devname, AGENT_RESULT *result)
100 {
101 	zbx_uint64_t	value;
102 	char		*error;
103 
104 	if (SYSINFO_RET_OK != get_disk_stats(devname, &value, NULL, NULL, NULL, &error))
105 	{
106 		SET_MSG_RESULT(result, error);
107 		return SYSINFO_RET_FAIL;
108 	}
109 
110 	SET_UI64_RESULT(result, value);
111 
112 	return SYSINFO_RET_OK;
113 }
114 
VFS_DEV_READ_OPERATIONS(const char * devname,AGENT_RESULT * result)115 static int	VFS_DEV_READ_OPERATIONS(const char *devname, AGENT_RESULT *result)
116 {
117 	zbx_uint64_t	value;
118 	char		*error;
119 
120 	if (SYSINFO_RET_OK != get_disk_stats(devname, NULL, NULL, &value, NULL, &error))
121 	{
122 		SET_MSG_RESULT(result, error);
123 		return SYSINFO_RET_FAIL;
124 	}
125 
126 	SET_UI64_RESULT(result, value);
127 
128 	return SYSINFO_RET_OK;
129 }
130 
VFS_DEV_WRITE_BYTES(const char * devname,AGENT_RESULT * result)131 static int	VFS_DEV_WRITE_BYTES(const char *devname, AGENT_RESULT *result)
132 {
133 	zbx_uint64_t	value;
134 	char		*error;
135 
136 	if (SYSINFO_RET_OK != get_disk_stats(devname, NULL, &value, NULL, NULL, &error))
137 	{
138 		SET_MSG_RESULT(result, error);
139 		return SYSINFO_RET_FAIL;
140 	}
141 
142 	SET_UI64_RESULT(result, value);
143 
144 	return SYSINFO_RET_OK;
145 }
146 
VFS_DEV_WRITE_OPERATIONS(const char * devname,AGENT_RESULT * result)147 static int	VFS_DEV_WRITE_OPERATIONS(const char *devname, AGENT_RESULT *result)
148 {
149 	zbx_uint64_t	value;
150 	char		*error;
151 
152 	if (SYSINFO_RET_OK != get_disk_stats(devname, NULL, NULL, NULL, &value, &error))
153 	{
154 		SET_MSG_RESULT(result, error);
155 		return SYSINFO_RET_FAIL;
156 	}
157 
158 	SET_UI64_RESULT(result, value);
159 
160 	return SYSINFO_RET_OK;
161 }
162 
VFS_DEV_READ(AGENT_REQUEST * request,AGENT_RESULT * result)163 int	VFS_DEV_READ(AGENT_REQUEST *request, AGENT_RESULT *result)
164 {
165 	char	*devname, *mode;
166 	int	ret;
167 
168 	if (2 < request->nparam)
169 	{
170 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
171 		return SYSINFO_RET_FAIL;
172 	}
173 
174 	devname = get_rparam(request, 0);
175 	mode = get_rparam(request, 1);
176 
177 	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "operations"))
178 		ret = VFS_DEV_READ_OPERATIONS(devname, result);
179 	else if (0 == strcmp(mode, "bytes"))
180 		ret = VFS_DEV_READ_BYTES(devname, result);
181 	else
182 	{
183 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
184 		return SYSINFO_RET_FAIL;
185 	}
186 
187 	return ret;
188 }
189 
VFS_DEV_WRITE(AGENT_REQUEST * request,AGENT_RESULT * result)190 int	VFS_DEV_WRITE(AGENT_REQUEST *request, AGENT_RESULT *result)
191 {
192 	char	*devname, *mode;
193 	int	ret;
194 
195 	if (2 < request->nparam)
196 	{
197 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
198 		return SYSINFO_RET_FAIL;
199 	}
200 
201 	devname = get_rparam(request, 0);
202 	mode = get_rparam(request, 1);
203 
204 	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "operations"))
205 		ret = VFS_DEV_WRITE_OPERATIONS(devname, result);
206 	else if (0 == strcmp(mode, "bytes"))
207 		ret = VFS_DEV_WRITE_BYTES(devname, result);
208 	else
209 	{
210 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
211 		return SYSINFO_RET_FAIL;
212 	}
213 
214 	return ret;
215 }
216