+ System.Memory.Swap.*
[public/netxms.git] / src / agent / subagents / freebsd / system.cpp
1 /* $Id: system.cpp,v 1.5 2005-01-23 05:36:11 alk Exp $ */
2
3 /*
4 ** NetXMS subagent for FreeBSD
5 ** Copyright (C) 2004 Alex Kirhenshtein
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 **
21 **/
22
23 #include <nms_common.h>
24 #include <nms_agent.h>
25
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <sys/sysctl.h>
29 #include <sys/utsname.h>
30 #include <sys/param.h>
31 #include <sys/user.h>
32 #include <fcntl.h>
33 #include <kvm.h>
34
35 #include "system.h"
36
37 LONG H_Uptime(char *pszParam, char *pArg, char *pValue)
38 {
39 int mib[2] = { CTL_KERN, KERN_BOOTTIME };
40 time_t nNow;
41 size_t nSize;
42 struct timeval bootTime;
43 time_t nUptime = 0;
44
45 nSize = sizeof(bootTime);
46
47 time(&nNow);
48 if (sysctl(mib, 2, &bootTime, &nSize, NULL, 0) != (-1))
49 {
50 nUptime = (time_t)(nNow - bootTime.tv_sec);
51 }
52 else
53 {
54 perror("uptime()");
55 }
56
57 if (nUptime > 0)
58 {
59 ret_uint(pValue, nUptime);
60 }
61
62 return nUptime > 0 ? SYSINFO_RC_SUCCESS : SYSINFO_RC_ERROR;
63 }
64
65 LONG H_Uname(char *pszParam, char *pArg, char *pValue)
66 {
67 struct utsname utsName;
68 int nRet = SYSINFO_RC_ERROR;
69
70 if (uname(&utsName) == 0)
71 {
72 char szBuff[1024];
73
74 snprintf(szBuff, sizeof(szBuff), "%s %s %s %s %s", utsName.sysname,
75 utsName.nodename, utsName.release, utsName.version,
76 utsName.machine);
77 // TODO: processor & platform
78
79 ret_string(pValue, szBuff);
80
81 nRet = SYSINFO_RC_SUCCESS;
82 }
83
84 return nRet;
85 }
86
87 LONG H_Hostname(char *pszParam, char *pArg, char *pValue)
88 {
89 int nRet = SYSINFO_RC_ERROR;
90 char szBuff[128];
91
92 if (gethostname(szBuff, sizeof(szBuff)) == 0)
93 {
94 ret_string(pValue, szBuff);
95 nRet = SYSINFO_RC_SUCCESS;
96 }
97
98 return nRet;
99 }
100
101 LONG H_CpuLoad(char *pszParam, char *pArg, char *pValue)
102 {
103 int nRet = SYSINFO_RC_ERROR;
104 char szArg[128] = {0};
105 FILE *hFile;
106 double dLoad[3];
107
108 // get processor
109 //NxGetParameterArg(pszParam, 1, szArg, sizeof(szArg));
110
111 if (getloadavg(dLoad, 3) == 3)
112 {
113 switch (pszParam[19])
114 {
115 case '1': // 15 min
116 ret_double(pValue, dLoad[2]);
117 break;
118 case '5': // 5 min
119 ret_double(pValue, dLoad[1]);
120 break;
121 default: // 1 min
122 ret_double(pValue, dLoad[0]);
123 break;
124 }
125 nRet = SYSINFO_RC_SUCCESS;
126 }
127
128 return nRet;
129 }
130
131 LONG H_CpuUsage(char *pszParam, char *pArg, char *pValue)
132 {
133 return SYSINFO_RC_UNSUPPORTED;
134 }
135
136 LONG H_CpuCount(char *pszParam, char *pArg, char *pValue)
137 {
138 int nRet = SYSINFO_RC_ERROR;
139 int mib[2];
140 size_t nSize = sizeof(mib), nValSize;
141 int nVal;
142
143 if (sysctlnametomib("hw.ncpu", mib, &nSize) != 0)
144 {
145 return SYSINFO_RC_ERROR;
146 }
147
148 nValSize = sizeof(nVal);
149 if (sysctl(mib, nSize, &nVal, &nValSize, NULL, 0) == 0)
150 {
151 ret_int(pValue, nVal);
152 nRet = SYSINFO_RC_SUCCESS;
153 }
154
155 return nRet;
156 }
157
158 LONG H_ProcessCount(char *pszParam, char *pArg, char *pValue)
159 {
160 int nRet = SYSINFO_RC_ERROR;
161 // struct statvfs s;
162 char szArg[128] = {0};
163 int nCount = -1;
164 struct kinfo_proc *pKInfo;
165 int mib[3];
166 size_t nSize;
167 int i;
168
169 NxGetParameterArg(pszParam, 1, szArg, sizeof(szArg));
170
171 nSize = sizeof(mib);
172 if (sysctlnametomib("kern.proc.all", mib, &nSize) == 0)
173 {
174 if (sysctl(mib, 3, NULL, &nSize, NULL, 0) == 0)
175 {
176 {
177 pKInfo = (struct kinfo_proc *)malloc(nSize);
178 if (pKInfo != NULL)
179 {
180 if (sysctl(mib, 3, pKInfo, &nSize, NULL, 0) == 0)
181 {
182 nCount = 0;
183 for (i = 0; i < (nSize / sizeof(struct kinfo_proc)); i++)
184 {
185 if (szArg[0] == 0 ||
186 strcasecmp(pKInfo[i].kp_proc.p_comm, szArg) == 0)
187 {
188 nCount++;
189 }
190 }
191 }
192 free(pKInfo);
193 }
194 }
195 }
196 }
197
198 if (nCount >= 0)
199 {
200 ret_int(pValue, nCount);
201 nRet = SYSINFO_RC_SUCCESS;
202 }
203
204 return nRet;
205 }
206
207 LONG H_MemoryInfo(char *pszParam, char *pArg, char *pValue)
208 {
209 int nRet = SYSINFO_RC_ERROR;
210 FILE *hFile;
211 int nPageCount, nFreeCount;
212 int64_t nSwapTotal, nSwapUsed;
213 char *pTag;
214 int mib[4];
215 size_t nSize;
216 int i;
217 char *pOid;
218 int nPageSize;
219 char szArg[16] = {0};
220 kvm_t *kd;
221 struct kvm_swap swap[16];
222
223 nPageCount = nFreeCount = 0;
224 nSwapTotal = nSwapUsed = 0;
225
226 NxGetParameterArg(pszParam, 1, szArg, sizeof(szArg));
227
228 #define DOIT(x, y) { \
229 nSize = sizeof(mib); \
230 if (sysctlnametomib(x, mib, &nSize) == 0) { \
231 size_t __nTmp = sizeof(y); \
232 if (sysctl(mib, nSize, &y, &__nTmp, NULL, 0) == 0) { \
233 nRet = SYSINFO_RC_SUCCESS; \
234 } else { \
235 perror(x ": sysctl()"); \
236 } \
237 } else { \
238 perror(x ": sysctlnametomib()"); \
239 } \
240 }
241
242 nPageSize = getpagesize();
243
244 // Phisical memory
245
246 DOIT("vm.stats.vm.v_page_count", nPageCount);
247
248 if (nRet == SYSINFO_RC_SUCCESS)
249 {
250 nRet = SYSINFO_RC_ERROR;
251 DOIT("vm.stats.vm.v_free_count", nFreeCount);
252 }
253
254 #undef DOIT
255
256 // Swap
257
258 kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open");
259 if (kd != NULL)
260 {
261 i = kvm_getswapinfo(kd, swap, 16, 0);
262 while (i > 0)
263 {
264 i--;
265 nSwapTotal += swap[i].ksw_total;
266 nSwapUsed += swap[i].ksw_used;
267 }
268 kvm_close(kd);
269 }
270 else
271 {
272 if ((int)pArg != PHYSICAL_FREE &&
273 (int)pArg != PHYSICAL_TOTAL &&
274 (int)pArg != PHYSICAL_USED)
275 nRet = SYSINFO_RC_ERROR;
276 }
277
278 if (nRet == SYSINFO_RC_SUCCESS)
279 {
280 switch((int)pArg)
281 {
282 case PHYSICAL_FREE: // ph-free
283 ret_uint64(pValue, ((int64_t)nFreeCount) * nPageSize);
284 break;
285 case PHYSICAL_TOTAL: // ph-total
286 ret_uint64(pValue, ((int64_t)nPageCount) * nPageSize);
287 break;
288 case PHYSICAL_USED: // ph-used
289 ret_uint64(pValue, ((int64_t)(nPageCount - nFreeCount)) * nPageSize);
290 break;
291 case SWAP_FREE: // sw-free
292 ret_uint64(pValue, (nSwapTotal - nSwapUsed) * nPageSize);
293 break;
294 case SWAP_TOTAL: // sw-total
295 ret_uint64(pValue, nSwapTotal * nPageSize);
296 break;
297 case SWAP_USED: // sw-used
298 ret_uint64(pValue, nSwapUsed * nPageSize);
299 break;
300 case VIRTUAL_FREE: // vi-free
301 ret_uint64(pValue, ((nSwapTotal - nSwapUsed) * nPageSize) +
302 (((int64_t)nFreeCount) * nPageSize));
303 break;
304 case VIRTUAL_TOTAL: // vi-total
305 ret_uint64(pValue, (nSwapTotal * nPageSize) +
306 (((int64_t)nPageCount) * nPageSize));
307 break;
308 case VIRTUAL_USED: // vi-used
309 ret_uint64(pValue, (nSwapUsed * nPageSize) +
310 (((int64_t)(nPageCount - nFreeCount)) * nPageSize));
311 break;
312 default: // error
313 nRet = SYSINFO_RC_ERROR;
314 break;
315 }
316 }
317
318 return nRet;
319 }
320
321 LONG H_ProcessList(char *pszParam, char *pArg, NETXMS_VALUES_LIST *pValue)
322 {
323 int nRet = SYSINFO_RC_ERROR;
324 int nCount = -1;
325 struct kinfo_proc *pKInfo;
326 int mib[3];
327 size_t nSize;
328 int i;
329
330 nSize = sizeof(mib);
331 if (sysctlnametomib("kern.proc.all", mib, &nSize) == 0)
332 {
333 if (sysctl(mib, 3, NULL, &nSize, NULL, 0) == 0)
334 {
335 {
336 pKInfo = (struct kinfo_proc *)malloc(nSize);
337 if (pKInfo != NULL)
338 {
339 if (sysctl(mib, 3, pKInfo, &nSize, NULL, 0) == 0)
340 {
341 nCount = 0;
342 for (i = 0; i < (nSize / sizeof(struct kinfo_proc)); i++)
343 {
344 char szBuff[128];
345
346 snprintf(szBuff, sizeof(szBuff), "%d %s",
347 pKInfo[i].kp_proc.p_pid, pKInfo[i].kp_proc.p_comm);
348 NxAddResultString(pValue, szBuff);
349
350 nCount++;
351 }
352 }
353 free(pKInfo);
354 }
355 }
356 }
357 }
358
359 if (nCount >= 0)
360 {
361 nRet = SYSINFO_RC_SUCCESS;
362 }
363
364 return nRet;
365 }
366
367 //
368 // stub
369 //
370 LONG H_SourcePkgSupport(char *pszParam, char *pArg, char *pValue)
371 {
372 ret_int(pValue, 1);
373 return SYSINFO_RC_SUCCESS;
374 }
375
376
377 ///////////////////////////////////////////////////////////////////////////////
378 /*
379
380 $Log: not supported by cvs2svn $
381 Revision 1.4 2005/01/23 05:14:49 alk
382 System's PageSize used instead of Hardware PageSize
383
384 Revision 1.3 2005/01/23 05:08:06 alk
385 + System.CPU.Count
386 + System.Memory.Physical.*
387 + System.ProcessCount
388 + System.ProcessList
389
390 Revision 1.2 2005/01/17 23:25:47 alk
391 Agent.SourcePackageSupport added
392
393 Revision 1.1 2005/01/17 17:14:32 alk
394 freebsd agent, incomplete (but working)
395
396 Revision 1.1 2004/10/22 22:08:35 alk
397 source restructured;
398 implemented:
399 Net.IP.Forwarding
400 Net.IP6.Forwarding
401 Process.Count(*)
402 Net.ArpCache
403 Net.InterfaceList (if-type not implemented yet)
404 System.ProcessList
405
406
407 */