and added files
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / ucd-snmp / memory_solaris2.c
1 #include <net-snmp/net-snmp-config.h>   /* local SNMP configuration details */
2 #if HAVE_STRING_H
3 #include <string.h>
4 #endif
5 #if HAVE_STDLIB_H
6 #include <stdlib.h>
7 #endif
8
9 #include <sys/types.h>
10
11 #if HAVE_DMALLOC_H
12 #include <dmalloc.h>
13 #endif
14
15 #include <net-snmp/net-snmp-includes.h>
16 #include <net-snmp/agent/net-snmp-agent-includes.h>
17 #include <net-snmp/agent/auto_nlist.h>
18
19 #include "util_funcs.h"         /* utility function declarations */
20 #include "memory.h"             /* the module-specific header */
21 #include "memory_solaris2.h"    /* the module-specific header */
22
23 #include <kstat.h>
24 #include <sys/stat.h>
25 #include <sys/swap.h>
26 #include <unistd.h>
27
28 #define MAXSTRSIZE      80
29
30 int             minimumswap;
31 static char     errmsg[300];
32 /****************************
33  * Kstat specific variables *
34  ****************************/
35 extern kstat_ctl_t *kstat_fd;   /* defined in kernel_sunos5.c */
36 kstat_t        *ksp1, *ksp2;
37 kstat_named_t  *kn, *kn2;
38
39 static FindVarMethod var_extensible_mem;
40 static long     getFreeSwap(void);
41 static long     getTotalFree(void);
42 static long     getTotalSwap(void);
43
44 void
45 init_memory_solaris2(void)
46 {
47
48     struct variable2 extensible_mem_variables[] = {
49         {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_mem, 1, {MIBINDEX}},
50         {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_mem, 1,
51          {ERRORNAME}},
52         {MEMTOTALSWAP, ASN_INTEGER, RONLY, var_extensible_mem, 1,
53          {MEMTOTALSWAP}},
54         {MEMAVAILSWAP, ASN_INTEGER, RONLY, var_extensible_mem, 1,
55          {MEMAVAILSWAP}},
56         {MEMTOTALREAL, ASN_INTEGER, RONLY, var_extensible_mem, 1,
57          {MEMTOTALREAL}},
58         {MEMAVAILREAL, ASN_INTEGER, RONLY, var_extensible_mem, 1,
59          {MEMAVAILREAL}},
60         {MEMTOTALSWAPTXT, ASN_INTEGER, RONLY, var_extensible_mem, 1,
61          {MEMTOTALSWAPTXT}},
62         {MEMUSEDSWAPTXT, ASN_INTEGER, RONLY, var_extensible_mem, 1,
63          {MEMUSEDSWAPTXT}},
64         {MEMTOTALREALTXT, ASN_INTEGER, RONLY, var_extensible_mem, 1,
65          {MEMTOTALREALTXT}},
66         {MEMUSEDREALTXT, ASN_INTEGER, RONLY, var_extensible_mem, 1,
67          {MEMUSEDREALTXT}},
68         {MEMTOTALFREE, ASN_INTEGER, RONLY, var_extensible_mem, 1,
69          {MEMTOTALFREE}},
70         {MEMSWAPMINIMUM, ASN_INTEGER, RONLY, var_extensible_mem, 1,
71          {MEMSWAPMINIMUM}},
72         {MEMSHARED, ASN_INTEGER, RONLY, var_extensible_mem, 1,
73          {MEMSHARED}},
74         {MEMBUFFER, ASN_INTEGER, RONLY, var_extensible_mem, 1,
75          {MEMBUFFER}},
76         {MEMCACHED, ASN_INTEGER, RONLY, var_extensible_mem, 1,
77          {MEMCACHED}},
78         {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_mem, 1,
79          {ERRORFLAG}},
80         {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_mem, 1, {ERRORMSG}}
81     };
82
83     /*
84      * Define the OID pointer to the top of the mib tree that we're
85      * registering underneath 
86      */
87     oid             mem_variables_oid[] = { UCDAVIS_MIB, MEMMIBNUM };
88
89     /*
90      * register ourselves with the agent to handle our mib tree 
91      */
92     REGISTER_MIB("ucd-snmp/memory", extensible_mem_variables, variable2,
93                  mem_variables_oid);
94
95     snmpd_register_config_handler("swap", memory_parse_config,
96                                   memory_free_config, "min-avail");
97
98     if (kstat_fd == 0) {
99         kstat_fd = kstat_open();
100         if (kstat_fd == 0) {
101             snmp_log(LOG_ERR, "kstat_open(): failed\n");
102         }
103     }
104 }
105
106 static u_char  *
107 var_extensible_mem(struct variable *vp,
108                    oid * name,
109                    size_t * length,
110                    int exact,
111                    size_t * var_len, WriteMethod ** write_method)
112 {
113     static long     long_ret;
114
115     /*
116      * Initialize the return value to 0 
117      */
118     long_ret = 0;
119
120     if (header_generic(vp, name, length, exact, var_len, write_method))
121         return (NULL);
122
123     switch (vp->magic) {
124     case MIBINDEX:
125         long_ret = 0;
126         return ((u_char *) (&long_ret));
127     case ERRORNAME:            /* dummy name */
128         sprintf(errmsg, "swap");
129         *var_len = strlen(errmsg);
130         return ((u_char *) (errmsg));
131     case MEMTOTALSWAP:
132         long_ret = getTotalSwap() * (getpagesize() / 1024);
133         return ((u_char *) (&long_ret));
134     case MEMAVAILSWAP:
135         long_ret = getFreeSwap() * (getpagesize() / 1024);
136         return ((u_char *) (&long_ret));
137     case MEMSWAPMINIMUM:
138         long_ret = minimumswap;
139         return ((u_char *) (&long_ret));
140     case MEMTOTALREAL:
141 #ifdef _SC_PHYS_PAGES
142         long_ret = sysconf(_SC_PHYS_PAGES) * (getpagesize()/1024);
143 #else
144         ksp1 = kstat_lookup(kstat_fd, "unix", 0, "system_pages");
145         kstat_read(kstat_fd, ksp1, 0);
146         kn = kstat_data_lookup(ksp1, "physmem");
147
148         long_ret = kn->value.ul * (getpagesize() / 1024);
149 #endif
150         return ((u_char *) (&long_ret));
151     case MEMAVAILREAL:
152 #ifdef _SC_AVPHYS_PAGES
153         long_ret = sysconf(_SC_AVPHYS_PAGES) * (getpagesize()/1024);
154 #else
155         long_ret =
156             (getTotalFree() - getFreeSwap()) * (getpagesize() / 1024);
157 #endif
158         return ((u_char *) (&long_ret));
159     case MEMTOTALFREE:
160         long_ret = getTotalFree() * (getpagesize() / 1024);
161         return ((u_char *) (&long_ret));
162
163     case ERRORFLAG:
164         long_ret = getTotalFree() * (getpagesize() / 1024);
165         long_ret = (long_ret > minimumswap) ? 0 : 1;
166         return ((u_char *) (&long_ret));
167
168     case ERRORMSG:
169         long_ret = getTotalFree() * (getpagesize() / 1024);
170         if ((long_ret > minimumswap) ? 0 : 1)
171             sprintf(errmsg, "Running out of swap space (%ld)", long_ret);
172         else
173             errmsg[0] = 0;
174         *var_len = strlen(errmsg);
175         return ((u_char *) (errmsg));
176
177     }
178
179     return (NULL);
180 }
181
182 #define DEFAULTMINIMUMSWAP 16000        /* kilobytes */
183
184 void
185 memory_parse_config(const char *token, char *cptr)
186 {
187     minimumswap = atoi(cptr);
188 }
189
190 void
191 memory_free_config(void)
192 {
193     minimumswap = DEFAULTMINIMUMSWAP;
194 }
195
196 long
197 getTotalSwap(void)
198 {
199     long            total_mem;
200
201     size_t          num;
202     int             i, n;
203     swaptbl_t      *s;
204     char           *strtab;
205
206     total_mem = 0;
207
208     num = swapctl(SC_GETNSWP, 0);
209     s = malloc(num * sizeof(swapent_t) + sizeof(struct swaptable));
210     if (s) {
211         strtab = (char *) malloc((num + 1) * MAXSTRSIZE);
212         if (strtab) {
213             for (i = 0; i < (num + 1); i++) {
214                 s->swt_ent[i].ste_path = strtab + (i * MAXSTRSIZE);
215             }
216             s->swt_n = num + 1;
217             n = swapctl(SC_LIST, s);
218
219             for (i = 0; i < n; i++)
220                 total_mem += s->swt_ent[i].ste_pages;
221
222             free(strtab);
223         }
224         free(s);
225     }
226
227     return (total_mem);
228 }
229
230 /*
231  * returns -1 if malloc fails.
232  */
233 static long
234 getFreeSwap(void)
235 {
236     long            free_mem = -1;
237
238     size_t          num;
239     int             i, n;
240     swaptbl_t      *s;
241     char           *strtab;
242
243     num = swapctl(SC_GETNSWP, 0);
244     s = malloc(num * sizeof(swapent_t) + sizeof(struct swaptable));
245     if (s) {
246         strtab = (char *) malloc((num + 1) * MAXSTRSIZE);
247         if (strtab) {
248             free_mem = 0;
249             for (i = 0; i < (num + 1); i++) {
250                 s->swt_ent[i].ste_path = strtab + (i * MAXSTRSIZE);
251             }
252             s->swt_n = num + 1;
253             n = swapctl(SC_LIST, s);
254
255             for (i = 0; i < n; i++)
256                 free_mem += s->swt_ent[i].ste_free;
257
258             free(strtab);
259         }
260         free(s);
261     }
262
263     return (free_mem);
264 }
265
266 static long
267 getTotalFree(void)
268 {
269     unsigned long   free_mem, allocated, reserved, available, used_size;
270     struct anoninfo ai;
271
272     if (-1 == swapctl(SC_AINFO, &ai)) {
273         snmp_log(LOG_ERR, "error swapctl\n");
274     }
275     allocated = ai.ani_max - ai.ani_free;
276     reserved = (ai.ani_resv - allocated);
277     available = (ai.ani_max - ai.ani_resv);     /* K-byte */
278     free_mem = used_size = reserved + allocated;
279     free_mem = available;
280     return (free_mem);
281 }