# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / host / hr_device.c
1 /*
2  *  Host Resources MIB - Device group implementation - hr_device.c
3  *
4  */
5
6 #include <net-snmp/net-snmp-config.h>
7 #if HAVE_STRING_H
8 #include <string.h>
9 #else
10 #include <strings.h>
11 #endif
12
13 #include "host_res.h"
14 #include "hr_device.h"
15
16         /*********************
17          *
18          *  Kernel & interface information,
19          *   and internal forward declarations
20          *
21          *********************/
22
23 int             Get_Next_Device(void);
24
25 PFV             init_device[HRDEV_TYPE_MAX];
26 PFIV            next_device[HRDEV_TYPE_MAX];
27 PFV             save_device[HRDEV_TYPE_MAX];
28 int             dev_idx_inc[HRDEV_TYPE_MAX];
29
30 PFS             device_descr[HRDEV_TYPE_MAX];
31 PFO             device_prodid[HRDEV_TYPE_MAX];
32 PFI             device_status[HRDEV_TYPE_MAX];
33 PFI             device_errors[HRDEV_TYPE_MAX];
34
35 int             current_type;
36
37 void            Init_Device(void);
38 int             header_hrdevice(struct variable *, oid *, size_t *, int,
39                                 size_t *, WriteMethod **);
40
41
42         /*********************
43          *
44          *  Initialisation & common implementation functions
45          *
46          *********************/
47
48 #define HRDEV_INDEX             1
49 #define HRDEV_TYPE              2
50 #define HRDEV_DESCR             3
51 #define HRDEV_ID                4
52 #define HRDEV_STATUS            5
53 #define HRDEV_ERRORS            6
54
55 struct variable4 hrdevice_variables[] = {
56     {HRDEV_INDEX, ASN_INTEGER, RONLY, var_hrdevice, 2, {1, 1}},
57     {HRDEV_TYPE, ASN_OBJECT_ID, RONLY, var_hrdevice, 2, {1, 2}},
58     {HRDEV_DESCR, ASN_OCTET_STR, RONLY, var_hrdevice, 2, {1, 3}},
59     {HRDEV_ID, ASN_OBJECT_ID, RONLY, var_hrdevice, 2, {1, 4}},
60     {HRDEV_STATUS, ASN_INTEGER, RONLY, var_hrdevice, 2, {1, 5}},
61     {HRDEV_ERRORS, ASN_COUNTER, RONLY, var_hrdevice, 2, {1, 6}}
62 };
63 oid             hrdevice_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 2 };
64
65
66 void
67 init_hr_device(void)
68 {
69     int             i;
70
71     /*
72      * Initially assume no devices
73      *    Insert pointers to initialisation/get_next routines
74      *    for particular device types as they are implemented
75      *      (set up in the appropriate 'init_*()' routine )
76      */
77
78     for (i = 0; i < HRDEV_TYPE_MAX; ++i) {
79         init_device[i] = NULL;
80         next_device[i] = NULL;
81         save_device[i] = NULL;
82         dev_idx_inc[i] = 0;     /* Assume random indices */
83
84         device_descr[i] = NULL;
85         device_prodid[i] = NULL;
86         device_status[i] = NULL;
87         device_errors[i] = NULL;
88     }
89
90     REGISTER_MIB("host/hr_device", hrdevice_variables, variable4,
91                  hrdevice_variables_oid);
92 }
93
94
95 /*
96  * header_hrdevice(...
97  * Arguments:
98  * vp     IN      - pointer to variable entry that points here
99  * name    IN/OUT  - IN/name requested, OUT/name found
100  * length  IN/OUT  - length of IN/OUT oid's 
101  * exact   IN      - TRUE if an exact match was requested
102  * var_len OUT     - length of variable or 0 if function returned
103  * write_method
104  * 
105  */
106
107 int
108 header_hrdevice(struct variable *vp,
109                 oid * name,
110                 size_t * length,
111                 int exact, size_t * var_len, WriteMethod ** write_method)
112 {
113 #define HRDEV_ENTRY_NAME_LENGTH 11
114     oid             newname[MAX_OID_LEN];
115     int             dev_idx, LowIndex = -1, LowType = -1;
116     int             result;
117
118     DEBUGMSGTL(("host/hr_device", "var_hrdevice: "));
119     DEBUGMSGOID(("host/hr_device", name, *length));
120     DEBUGMSG(("host/hr_device", " %d\n", exact));
121
122     memcpy((char *) newname, (char *) vp->name,
123            (int) vp->namelen * sizeof(oid));
124
125
126     /*
127      *  Find the "next" device entry.
128      *  If we're in the middle of the table, then there's
129      *     no point in examining earlier types of devices,
130      *     so set the starting type to that of the variable
131      *     being queried.
132      *  If we've moved from one column of the table to another,
133      *     then we need to start at the beginning again.
134      *     (i.e. the 'compare' fails to match)
135      *  Similarly if we're at the start of the table
136      *     (i.e. *length is too short to be a full instance)
137      */
138
139     if ((snmp_oid_compare(vp->name, vp->namelen, name, vp->namelen) == 0)
140         && (*length > HRDEV_ENTRY_NAME_LENGTH))
141         current_type = (name[HRDEV_ENTRY_NAME_LENGTH] >> HRDEV_TYPE_SHIFT);
142     else
143         current_type = 0;
144
145     Init_Device();
146     for (;;) {
147         dev_idx = Get_Next_Device();
148         DEBUGMSG(("host/hr_device", "(index %d ....", dev_idx));
149         if (dev_idx == -1)
150             break;
151         if (LowType != -1 && LowType < (dev_idx >> HRDEV_TYPE_SHIFT))
152             break;
153         newname[HRDEV_ENTRY_NAME_LENGTH] = dev_idx;
154         DEBUGMSGOID(("host/hr_device", newname, *length));
155         DEBUGMSG(("host/hr_device", "\n"));
156         result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
157         if (exact && (result == 0)) {
158             if (save_device[current_type] != NULL)
159                 (*save_device[current_type]) ();
160             LowIndex = dev_idx;
161             break;
162         }
163         if ((!exact && (result < 0)) &&
164             (LowIndex == -1 || dev_idx < LowIndex)) {
165             if (save_device[current_type] != NULL)
166                 (*save_device[current_type]) ();
167             LowIndex = dev_idx;
168             LowType = (dev_idx >> HRDEV_TYPE_SHIFT);
169             if (dev_idx_inc[LowType])   /* Increasing indices => now done */
170                 break;
171         }
172
173     }
174
175     if (LowIndex == -1) {
176         DEBUGMSGTL(("host/hr_device", "... index out of range\n"));
177         return (MATCH_FAILED);
178     }
179
180     newname[HRDEV_ENTRY_NAME_LENGTH] = LowIndex;
181     memcpy((char *) name, (char *) newname,
182            ((int) vp->namelen + 1) * sizeof(oid));
183     *length = vp->namelen + 1;
184     *write_method = 0;
185     *var_len = sizeof(long);    /* default to 'long' results */
186
187     DEBUGMSGTL(("host/hr_device", "... get device stats "));
188     DEBUGMSGOID(("host/hr_device", name, *length));
189     DEBUGMSG(("host/hr_device", "\n"));
190
191     return LowIndex;
192 }
193
194
195 oid             device_type_id[] = { 1, 3, 6, 1, 2, 1, 25, 3, 1, 99 };  /* hrDeviceType99 */
196 int             device_type_len =
197     sizeof(device_type_id) / sizeof(device_type_id[0]);
198
199
200         /*********************
201          *
202          *  System specific implementation functions
203          *
204          *********************/
205
206
207 u_char         *
208 var_hrdevice(struct variable *vp,
209              oid * name,
210              size_t * length,
211              int exact, size_t * var_len, WriteMethod ** write_method)
212 {
213     int             dev_idx, type;
214     oid            *oid_p;
215     static char     string[100];
216
217     dev_idx =
218         header_hrdevice(vp, name, length, exact, var_len, write_method);
219     if (dev_idx == MATCH_FAILED)
220         return NULL;
221
222     type = (dev_idx >> HRDEV_TYPE_SHIFT);
223
224     switch (vp->magic) {
225     case HRDEV_INDEX:
226         long_return = dev_idx;
227         return (u_char *) & long_return;
228     case HRDEV_TYPE:
229         device_type_id[device_type_len - 1] = type;
230         *var_len = sizeof(device_type_id);
231         return (u_char *) device_type_id;
232     case HRDEV_DESCR:
233         if (device_descr[type] != NULL) {
234             strncpy(string, ((*device_descr[type]) (dev_idx)),
235                     sizeof(string)-1);
236             string[ sizeof(string)-1] = 0;
237         } else
238 #if NO_DUMMY_VALUES
239             return NULL;
240 #else
241             sprintf(string, "a black box of some sort");
242 #endif
243         *var_len = strlen(string);
244         return (u_char *) string;
245     case HRDEV_ID:
246         if (device_prodid[type] != NULL)
247             oid_p = ((*device_prodid[type]) (dev_idx, var_len));
248         else {
249             oid_p = nullOid;
250             *var_len = nullOidLen;
251         }
252         return (u_char *) oid_p;
253     case HRDEV_STATUS:
254         if (device_status[type] != NULL)
255             long_return = ((*device_status[type]) (dev_idx));
256         else
257 #if NO_DUMMY_VALUES
258             return NULL;
259 #else
260             long_return = 2;    /* Assume running */
261 #endif
262         return (u_char *) & long_return;
263     case HRDEV_ERRORS:
264         if (device_errors[type] != NULL)
265             long_return = (*device_errors[type]) (dev_idx);
266         else
267 #if NO_DUMMY_VALUES
268             return NULL;
269 #else
270             long_return = 0;    /* Assume OK */
271 #endif
272         return (u_char *) & long_return;
273     default:
274         DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrdevice\n",
275                     vp->magic));
276     }
277     return NULL;
278 }
279
280
281         /*********************
282          *
283          *  Internal implementation functions
284          *
285          *********************/
286
287
288 void
289 Init_Device(void)
290 {
291     /*
292      *  Find the first non-NULL initialisation function
293      *    and call it
294      */
295     while (current_type < HRDEV_TYPE_MAX &&
296            init_device[current_type] == NULL)
297         if (++current_type >= HRDEV_TYPE_MAX)
298             return;
299     (*init_device[current_type]) ();
300 }
301
302 int
303 Get_Next_Device(void)
304 {
305     int             result = -1;
306
307     /*
308      *  Call the 'next device' function for the current
309      *    type of device
310      *
311      *  TODO:  save the necessary information about that device
312      */
313     if (current_type < HRDEV_TYPE_MAX && next_device[current_type] != NULL)
314         result = (*next_device[current_type]) ();
315
316     /*
317      *  No more devices of the current type.
318      *  Try the next type (if any)
319      */
320     if (result == -1) {
321         if (++current_type >= HRDEV_TYPE_MAX) {
322             current_type = 0;
323             return -1;
324         }
325         Init_Device();
326         return Get_Next_Device();
327     }
328     return result;
329 }