# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / ucd-snmp / loadave.c
1 #include <net-snmp/net-snmp-config.h>
2
3 #if HAVE_STDLIB_H
4 #include <stdlib.h>
5 #endif
6 #if HAVE_UNISTD_H
7 #include <unistd.h>
8 #endif
9 #if HAVE_FCNTL_H
10 #include <fcntl.h>
11 #endif
12 #include <signal.h>
13 #if HAVE_MACHINE_PARAM_H
14 #include <machine/param.h>
15 #endif
16 #if HAVE_SYS_PARAM_H
17 #include <sys/param.h>
18 #endif
19 #if HAVE_SYS_VMMETER_H
20 #if !(defined(bsdi2) || defined(netbsd1))
21 #include <sys/vmmeter.h>
22 #endif
23 #endif
24 #if HAVE_SYS_CONF_H
25 #include <sys/conf.h>
26 #endif
27 #if HAVE_ASM_PAGE_H
28 #include <asm/page.h>
29 #endif
30 #if HAVE_SYS_SWAP_H
31 #include <sys/swap.h>
32 #endif
33 #if HAVE_SYS_FS_H
34 #include <sys/fs.h>
35 #else
36 #if HAVE_UFS_FS_H
37 #include <ufs/fs.h>
38 #else
39 #ifdef HAVE_SYS_STAT_H
40 #include <sys/stat.h>
41 #endif
42 #ifdef HAVE_SYS_VNODE_H
43 #include <sys/vnode.h>
44 #endif
45 #ifdef HAVE_UFS_UFS_QUOTA_H
46 #include <ufs/ufs/quota.h>
47 #endif
48 #ifdef HAVE_UFS_UFS_INODE_H
49 #include <ufs/ufs/inode.h>
50 #endif
51 #if HAVE_UFS_FFS_FS_H
52 #include <ufs/ffs/fs.h>
53 #endif
54 #endif
55 #endif
56 #if HAVE_MTAB_H
57 #include <mtab.h>
58 #endif
59 #include <sys/stat.h>
60 #include <errno.h>
61 #if HAVE_FSTAB_H
62 #include <fstab.h>
63 #endif
64 #if HAVE_SYS_STATFS_H
65 #include <sys/statfs.h>
66 #endif
67 #if HAVE_SYS_STATVFS_H
68 #include <sys/statvfs.h>
69 #endif
70 #if HAVE_SYS_VFS_H
71 #include <sys/vfs.h>
72 #endif
73 #if (!defined(HAVE_STATVFS)) && defined(HAVE_STATFS)
74 #if HAVE_SYS_MOUNT_H
75 #include <sys/mount.h>
76 #endif
77 #if HAVE_SYS_SYSCTL_H
78 #include <sys/sysctl.h>
79 #endif
80 #define statvfs statfs
81 #endif
82 #if HAVE_VM_VM_H
83 #include <vm/vm.h>
84 #endif
85 #if HAVE_VM_SWAP_PAGER_H
86 #include <vm/swap_pager.h>
87 #endif
88 #if HAVE_SYS_FIXPOINT_H
89 #include <sys/fixpoint.h>
90 #endif
91 #if HAVE_SYS_LOADAVG_H
92 #include <sys/loadavg.h>
93 #endif
94 #if HAVE_MALLOC_H
95 #include <malloc.h>
96 #endif
97 #if HAVE_STRING_H
98 #include <string.h>
99 #endif
100 #if TIME_WITH_SYS_TIME
101 # ifdef WIN32
102 #  include <sys/timeb.h>
103 # else
104 #  include <sys/time.h>
105 # endif
106 # include <time.h>
107 #else
108 # if HAVE_SYS_TIME_H
109 #  include <sys/time.h>
110 # else
111 #  include <time.h>
112 # endif
113 #endif
114 #if HAVE_WINSOCK_H
115 #include <winsock.h>
116 #endif
117 #ifdef dynix
118 #include <sys/mc_vmparam.h>
119 #endif
120 #if defined(hpux10) || defined(hpux11)
121 #include <sys/pstat.h>
122 #endif
123
124 #include <net-snmp/net-snmp-includes.h>
125 #include <net-snmp/agent/net-snmp-agent-includes.h>
126 #include <net-snmp/agent/auto_nlist.h>
127
128 #include "struct.h"
129 #include "loadave.h"
130 #include "util_funcs.h"
131 #include "kernel.h"
132
133 double          maxload[3];
134
135 void
136 init_loadave(void)
137 {
138
139     /*
140      * define the structure we're going to ask the agent to register our
141      * information at 
142      */
143     struct variable2 extensible_loadave_variables[] = {
144         {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_loadave, 1,
145          {MIBINDEX}},
146         {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_loadave, 1,
147          {ERRORNAME}},
148         {LOADAVE, ASN_OCTET_STR, RONLY, var_extensible_loadave, 1,
149          {LOADAVE}},
150         {LOADMAXVAL, ASN_OCTET_STR, RONLY, var_extensible_loadave, 1,
151          {LOADMAXVAL}},
152         {LOADAVEINT, ASN_INTEGER, RONLY, var_extensible_loadave, 1,
153          {LOADAVEINT}},
154 #ifdef OPAQUE_SPECIAL_TYPES
155         {LOADAVEFLOAT, ASN_OPAQUE_FLOAT, RONLY, var_extensible_loadave, 1,
156          {LOADAVEFLOAT}},
157 #endif
158         {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_loadave, 1,
159          {ERRORFLAG}},
160         {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_loadave, 1,
161          {ERRORMSG}}
162     };
163
164     /*
165      * Define the OID pointer to the top of the mib tree that we're
166      * registering underneath 
167      */
168     oid             loadave_variables_oid[] =
169         { UCDAVIS_MIB, LOADAVEMIBNUM, 1 };
170
171     /*
172      * register ourselves with the agent to handle our mib tree 
173      */
174     REGISTER_MIB("ucd-snmp/loadave", extensible_loadave_variables,
175                  variable2, loadave_variables_oid);
176
177     snmpd_register_config_handler("load", loadave_parse_config,
178                                   loadave_free_config,
179                                   "max1 [max5] [max15]");
180 }
181
182 void
183 loadave_parse_config(const char *token, char *cptr)
184 {
185     int             i;
186
187     for (i = 0; i <= 2; i++) {
188         if (cptr != NULL)
189             maxload[i] = atof(cptr);
190         else
191             maxload[i] = maxload[i - 1];
192         cptr = skip_not_white(cptr);
193         cptr = skip_white(cptr);
194     }
195 }
196
197 void
198 loadave_free_config(void)
199 {
200     int             i;
201
202     for (i = 0; i <= 2; i++)
203         maxload[i] = DEFMAXLOADAVE;
204 }
205
206 /*
207  * try to get load average
208  * Inputs: pointer to array of doubles, number of elements in array
209  * Returns: 0=array has values, -1=error occurred.
210  */
211 int
212 try_getloadavg(double *r_ave, size_t s_ave)
213 {
214     double         *pave = r_ave;
215 #ifdef HAVE_SYS_FIXPOINT_H
216     fix             favenrun[3];
217 #endif
218 #if (defined(ultrix) || defined(sun) || defined(__alpha) || defined(dynix))
219     int             i;
220 #if (defined(sun) || defined(__alpha) || defined(dynix))
221     long            favenrun[3];
222     if (s_ave > 3)              /* bounds check */
223         return (-1);
224 #define FIX_TO_DBL(_IN) (((double) _IN)/((double) FSCALE))
225 #endif
226 #endif
227 #ifdef aix4
228     int             favenrun[3];
229 #endif
230 #if defined(hpux10) || defined(hpux11)
231   struct pst_dynamic pst_buf;
232 #endif
233
234
235 #ifdef HAVE_GETLOADAVG
236     if (getloadavg(pave, s_ave) == -1)
237         return (-1);
238 #elif defined(linux)
239     {
240         FILE           *in = fopen("/proc/loadavg", "r");
241         if (!in) {
242             snmp_log(LOG_ERR, "snmpd: cannot open /proc/loadavg\n");
243             return (-1);
244         }
245         fscanf(in, "%lf %lf %lf", pave, (pave + 1), (pave + 2));
246         fclose(in);
247     }
248 #elif (defined(ultrix) || defined(sun) || defined(__alpha) || defined(dynix))
249     if (auto_nlist(LOADAVE_SYMBOL, (char *) favenrun, sizeof(favenrun)) ==
250         0)
251         return (-1);
252     for (i = 0; i < s_ave; i++)
253         *(pave + i) = FIX_TO_DBL(favenrun[i]);
254 #elif defined(hpux10) || defined(hpux11)
255     if (pstat_getdynamic(&pst_buf, sizeof(struct pst_dynamic), 1, 0) < 0)
256         return(-1);
257     r_ave[0] = pst_buf.psd_avg_1_min;
258     r_ave[1] = pst_buf.psd_avg_5_min;
259     r_ave[2] = pst_buf.psd_avg_15_min;
260 #elif !defined(cygwin)
261 #ifdef CAN_USE_NLIST
262 #if aix4
263     if (auto_nlist(LOADAVE_SYMBOL, (char *) favenrun, sizeof(favenrun)) ==
264         0)
265         return -1;
266     r_ave[0] = favenrun[0] / 65536.0;
267     r_ave[1] = favenrun[1] / 65536.0;
268     r_ave[2] = favenrun[2] / 65536.0;
269     return 0;
270 #else
271     if (auto_nlist(LOADAVE_SYMBOL, (char *) pave, sizeof(double) * s_ave)
272         == 0)
273 #endif
274 #endif
275         return (-1);
276 #endif
277     /*
278      * XXX
279      *   To calculate this, we need to compare
280      *   successive values of the kernel array
281      *   '_cp_times', and calculate the resulting
282      *   percentage changes.
283      *     This calculation needs to be performed
284      *   regularly - perhaps as a background process.
285      *
286      *   See the source to 'top' for full details.
287      *
288      * The linux SNMP HostRes implementation
289      *   uses 'avenrun[0]*100' as an approximation.
290      *   This is less than accurate, but has the
291      *   advantage of being simple to implement!
292      *
293      * I'm also assuming a single processor
294      */
295     return 0;
296 }
297
298 u_char         *
299 var_extensible_loadave(struct variable * vp,
300                        oid * name,
301                        size_t * length,
302                        int exact,
303                        size_t * var_len, WriteMethod ** write_method)
304 {
305
306     static long     long_ret;
307     static float    float_ret;
308     static char     errmsg[300];
309     double          avenrun[3];
310     if (header_simple_table
311         (vp, name, length, exact, var_len, write_method, 3))
312         return (NULL);
313     switch (vp->magic) {
314     case MIBINDEX:
315         long_ret = name[*length - 1];
316         return ((u_char *) (&long_ret));
317     case ERRORNAME:
318         sprintf(errmsg, "Load-%d", ((name[*length - 1] == 1) ? 1 :
319                                     ((name[*length - 1] == 2) ? 5 : 15)));
320         *var_len = strlen(errmsg);
321         return ((u_char *) (errmsg));
322     }
323     if (try_getloadavg(&avenrun[0], sizeof(avenrun) / sizeof(avenrun[0]))
324         == -1)
325         return (0);
326     switch (vp->magic) {
327     case LOADAVE:
328
329         sprintf(errmsg, "%.2f", avenrun[name[*length - 1] - 1]);
330         *var_len = strlen(errmsg);
331         return ((u_char *) (errmsg));
332     case LOADMAXVAL:
333         sprintf(errmsg, "%.2f", maxload[name[*length - 1] - 1]);
334         *var_len = strlen(errmsg);
335         return ((u_char *) (errmsg));
336     case LOADAVEINT:
337         long_ret = (u_long) (avenrun[name[*length - 1] - 1] * 100);
338         return ((u_char *) (&long_ret));
339 #ifdef OPAQUE_SPECIAL_TYPES
340     case LOADAVEFLOAT:
341         float_ret = (float) avenrun[name[*length - 1] - 1];
342         *var_len = sizeof(float_ret);
343         return ((u_char *) (&float_ret));
344 #endif
345     case ERRORFLAG:
346         long_ret = (maxload[name[*length - 1] - 1] != 0 &&
347                     avenrun[name[*length - 1] - 1] >=
348                     maxload[name[*length - 1] - 1]) ? 1 : 0;
349         return ((u_char *) (&long_ret));
350     case ERRORMSG:
351         if (maxload[name[*length - 1] - 1] != 0 &&
352             avenrun[name[*length - 1] - 1] >=
353             maxload[name[*length - 1] - 1]) {
354             sprintf(errmsg, "%d min Load Average too high (= %.2f)",
355                     (name[*length - 1] ==
356                      1) ? 1 : ((name[*length - 1] == 2) ? 5 : 15),
357                     avenrun[name[*length - 1] - 1]);
358         } else {
359             errmsg[0] = 0;
360         }
361         *var_len = strlen(errmsg);
362         return ((u_char *) errmsg);
363     }
364     return NULL;
365 }