added files
[bcm963xx.git] / userapps / opensource / net-snmp / agent / helpers / instance.c
1 #include <net-snmp/net-snmp-config.h>
2
3 #include <stdlib.h>
4 #if HAVE_STRING_H
5 #include <string.h>
6 #else
7 #include <strings.h>
8 #endif
9
10 #include <net-snmp/net-snmp-includes.h>
11 #include <net-snmp/agent/net-snmp-agent-includes.h>
12
13 #include <net-snmp/agent/instance.h>
14 #include <net-snmp/agent/serialize.h>
15 #include <net-snmp/agent/read_only.h>
16
17 #if HAVE_DMALLOC_H
18 #include <dmalloc.h>
19 #endif
20
21 /** @defgroup instance instance: process scalars and other instances easily.
22  *  @ingroup handler
23  *  @{
24  */
25 netsnmp_mib_handler *
26 netsnmp_get_instance_handler(void)
27 {
28     return netsnmp_create_handler("instance",
29                                   netsnmp_instance_helper_handler);
30 }
31
32 int
33 netsnmp_register_instance(netsnmp_handler_registration *reginfo)
34 {
35     netsnmp_inject_handler(reginfo, netsnmp_get_instance_handler());
36     return netsnmp_register_serialize(reginfo);
37 }
38
39 int
40 netsnmp_register_read_only_instance(netsnmp_handler_registration *reginfo)
41 {
42     netsnmp_inject_handler(reginfo, netsnmp_get_instance_handler());
43     netsnmp_inject_handler(reginfo, netsnmp_get_read_only_handler());
44     return netsnmp_register_serialize(reginfo);
45 }
46
47 static
48 netsnmp_handler_registration *
49 get_reg(const char *name,
50         const char *ourname,
51         oid * reg_oid, size_t reg_oid_len,
52         void *it,
53         int modes,
54         Netsnmp_Node_Handler * scalarh, Netsnmp_Node_Handler * subhandler)
55 {
56     netsnmp_handler_registration *myreg;
57     netsnmp_mib_handler *myhandler;
58
59     if (subhandler) {
60         myreg =
61             netsnmp_create_handler_registration(name,
62                                                 subhandler,
63                                                 reg_oid, reg_oid_len,
64                                                 modes);
65         myhandler = netsnmp_create_handler(ourname, scalarh);
66         myhandler->myvoid = (void *) it;
67         netsnmp_inject_handler(myreg, myhandler);
68     } else {
69         myreg =
70             netsnmp_create_handler_registration(name,
71                                                 scalarh,
72                                                 reg_oid, reg_oid_len,
73                                                 modes);
74         myreg->handler->myvoid = (void *) it;
75     }
76     return myreg;
77 }
78
79 int
80 netsnmp_register_read_only_ulong_instance(const char *name,
81                                           oid * reg_oid,
82                                           size_t reg_oid_len, u_long * it,
83                                           Netsnmp_Node_Handler *
84                                           subhandler)
85 {
86     netsnmp_handler_registration *myreg;
87
88     myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
89                     HANDLER_CAN_RONLY, netsnmp_instance_ulong_handler,
90                     subhandler);
91     return netsnmp_register_read_only_instance(myreg);
92 }
93
94 int
95 netsnmp_register_ulong_instance(const char *name,
96                                 oid * reg_oid, size_t reg_oid_len,
97                                 u_long * it,
98                                 Netsnmp_Node_Handler * subhandler)
99 {
100     netsnmp_handler_registration *myreg;
101
102     myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
103                     HANDLER_CAN_RWRITE, netsnmp_instance_ulong_handler,
104                     subhandler);
105     return netsnmp_register_instance(myreg);
106 }
107
108 int
109 netsnmp_register_read_only_counter32_instance(const char *name,
110                                               oid * reg_oid,
111                                               size_t reg_oid_len,
112                                               u_long * it,
113                                               Netsnmp_Node_Handler *
114                                               subhandler)
115 {
116     netsnmp_handler_registration *myreg;
117
118     myreg = get_reg(name, "counter32_handler", reg_oid, reg_oid_len, it,
119                     HANDLER_CAN_RWRITE, netsnmp_instance_counter32_handler,
120                     subhandler);
121     return netsnmp_register_read_only_instance(myreg);
122 }
123
124 int
125 netsnmp_register_read_only_long_instance(const char *name,
126                                          oid * reg_oid, size_t reg_oid_len,
127                                          long *it,
128                                          Netsnmp_Node_Handler * subhandler)
129 {
130     netsnmp_handler_registration *myreg;
131
132     myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
133                     HANDLER_CAN_RONLY, netsnmp_instance_long_handler,
134                     subhandler);
135     return netsnmp_register_read_only_instance(myreg);
136 }
137
138 int
139 netsnmp_register_long_instance(const char *name,
140                                oid * reg_oid, size_t reg_oid_len,
141                                long *it, Netsnmp_Node_Handler * subhandler)
142 {
143     netsnmp_handler_registration *myreg;
144
145     myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
146                     HANDLER_CAN_RWRITE, netsnmp_instance_long_handler,
147                     subhandler);
148     return netsnmp_register_instance(myreg);
149 }
150
151 int
152 netsnmp_register_read_only_int_instance(const char *name,
153                                 oid * reg_oid, size_t reg_oid_len,
154                                 int *it, Netsnmp_Node_Handler * subhandler)
155 {
156     netsnmp_handler_registration *myreg;
157
158     myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
159                     HANDLER_CAN_RONLY, netsnmp_instance_int_handler,
160                     subhandler);
161     return netsnmp_register_read_only_instance(myreg);
162 }
163
164   /*
165    * Compatibility with earlier (inconsistently named) routine
166    */
167 int
168 register_read_only_int_instance(const char *name,
169                                 oid * reg_oid, size_t reg_oid_len,
170                                 int *it, Netsnmp_Node_Handler * subhandler)
171 {
172   return netsnmp_register_read_only_int_instance(name,
173                                 reg_oid, reg_oid_len,
174                                 it, subhandler);
175 }
176
177 int
178 netsnmp_register_int_instance(const char *name,
179                               oid * reg_oid, size_t reg_oid_len,
180                               int *it, Netsnmp_Node_Handler * subhandler)
181 {
182     netsnmp_handler_registration *myreg;
183
184     myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
185                     HANDLER_CAN_RWRITE, netsnmp_instance_int_handler,
186                     subhandler);
187     return netsnmp_register_instance(myreg);
188 }
189
190 int
191 netsnmp_instance_ulong_handler(netsnmp_mib_handler *handler,
192                                netsnmp_handler_registration *reginfo,
193                                netsnmp_agent_request_info *reqinfo,
194                                netsnmp_request_info *requests)
195 {
196
197     u_long         *it = (u_long *) handler->myvoid;
198     u_long         *it_save;
199
200     DEBUGMSGTL(("netsnmp_instance_ulong_handler", "Got request:  %d\n",
201                 reqinfo->mode));
202
203     switch (reqinfo->mode) {
204         /*
205          * data requests 
206          */
207     case MODE_GET:
208         snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
209                                  (u_char *) it, sizeof(*it));
210         break;
211
212         /*
213          * SET requests.  Should only get here if registered RWRITE 
214          */
215     case MODE_SET_RESERVE1:
216         if (requests->requestvb->type != ASN_UNSIGNED)
217             netsnmp_set_request_error(reqinfo, requests,
218                                       SNMP_ERR_WRONGTYPE);
219         break;
220
221     case MODE_SET_RESERVE2:
222         /*
223          * store old info for undo later 
224          */
225         memdup((u_char **) & it_save, (u_char *) it, sizeof(u_long));
226         if (it_save == NULL) {
227             netsnmp_set_request_error(reqinfo, requests,
228                                       SNMP_ERR_RESOURCEUNAVAILABLE);
229             return SNMP_ERR_NOERROR;
230         }
231         netsnmp_request_add_list_data(requests,
232                                       netsnmp_create_data_list
233                                       (INSTANCE_HANDLER_NAME, it_save,
234                                        free));
235         break;
236
237     case MODE_SET_ACTION:
238         /*
239          * update current 
240          */
241         DEBUGMSGTL(("testhandler", "updated u_long %ul -> %ul\n", *it,
242                     *(requests->requestvb->val.integer)));
243         *it = *(requests->requestvb->val.integer);
244         break;
245
246     case MODE_SET_UNDO:
247         *it =
248             *((u_long *) netsnmp_request_get_list_data(requests,
249                                                        INSTANCE_HANDLER_NAME));
250         break;
251
252     case MODE_SET_COMMIT:
253     case MODE_SET_FREE:
254         /*
255          * nothing to do 
256          */
257         break;
258     }
259
260     if (handler->next && handler->next->access_method)
261         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
262                                          requests);
263
264     return SNMP_ERR_NOERROR;
265 }
266
267 int
268 netsnmp_instance_counter32_handler(netsnmp_mib_handler *handler,
269                                    netsnmp_handler_registration *reginfo,
270                                    netsnmp_agent_request_info *reqinfo,
271                                    netsnmp_request_info *requests)
272 {
273
274     u_long         *it = (u_long *) handler->myvoid;
275
276     DEBUGMSGTL(("netsnmp_instance_counter32_handler",
277                 "Got request:  %d\n", reqinfo->mode));
278
279     switch (reqinfo->mode) {
280         /*
281          * data requests 
282          */
283     case MODE_GET:
284         snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER,
285                                  (u_char *) it, sizeof(*it));
286         break;
287
288         /*
289          * SET requests.  Should only get here if registered RWRITE 
290          */
291     default:
292         snmp_log(LOG_ERR,
293                  "netsnmp_instance_counter32_handler: illegal mode\n");
294         netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
295         return SNMP_ERR_NOERROR;
296     }
297     if (handler->next && handler->next->access_method)
298         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
299                                          requests);
300     return SNMP_ERR_NOERROR;
301 }
302
303 int
304 netsnmp_instance_long_handler(netsnmp_mib_handler *handler,
305                               netsnmp_handler_registration *reginfo,
306                               netsnmp_agent_request_info *reqinfo,
307                               netsnmp_request_info *requests)
308 {
309
310     long           *it = (u_long *) handler->myvoid;
311     long           *it_save;
312
313     DEBUGMSGTL(("netsnmp_instance_long_handler", "Got request:  %d\n",
314                 reqinfo->mode));
315
316     switch (reqinfo->mode) {
317         /*
318          * data requests 
319          */
320     case MODE_GET:
321         snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
322                                  (u_char *) it, sizeof(*it));
323         break;
324
325         /*
326          * SET requests.  Should only get here if registered RWRITE 
327          */
328     case MODE_SET_RESERVE1:
329         if (requests->requestvb->type != ASN_INTEGER)
330             netsnmp_set_request_error(reqinfo, requests,
331                                       SNMP_ERR_WRONGTYPE);
332         break;
333
334     case MODE_SET_RESERVE2:
335         /*
336          * store old info for undo later 
337          */
338         memdup((u_char **) & it_save, (u_char *) it, sizeof(u_long));
339         if (it_save == NULL) {
340             netsnmp_set_request_error(reqinfo, requests,
341                                       SNMP_ERR_RESOURCEUNAVAILABLE);
342             return SNMP_ERR_NOERROR;
343         }
344         netsnmp_request_add_list_data(requests,
345                                       netsnmp_create_data_list
346                                       (INSTANCE_HANDLER_NAME, it_save,
347                                        free));
348         break;
349
350     case MODE_SET_ACTION:
351         /*
352          * update current 
353          */
354         DEBUGMSGTL(("testhandler", "updated u_long %ul -> %ul\n", *it,
355                     *(requests->requestvb->val.integer)));
356         *it = *(requests->requestvb->val.integer);
357         break;
358
359     case MODE_SET_UNDO:
360         *it =
361             *((u_long *) netsnmp_request_get_list_data(requests,
362                                                        INSTANCE_HANDLER_NAME));
363         break;
364
365     case MODE_SET_COMMIT:
366     case MODE_SET_FREE:
367         /*
368          * nothing to do 
369          */
370         break;
371     }
372     if (handler->next && handler->next->access_method)
373         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
374                                          requests);
375     return SNMP_ERR_NOERROR;
376 }
377
378 int
379 netsnmp_instance_int_handler(netsnmp_mib_handler *handler,
380                              netsnmp_handler_registration *reginfo,
381                              netsnmp_agent_request_info *reqinfo,
382                              netsnmp_request_info *requests)
383 {
384
385     int            *it = (u_int *) handler->myvoid;
386     int            *it_save;
387
388     DEBUGMSGTL(("netsnmp_instance_int_handler", "Got request:  %d\n",
389                 reqinfo->mode));
390
391     switch (reqinfo->mode) {
392         /*
393          * data requests 
394          */
395     case MODE_GET:
396         snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
397                                  (u_char *) it, sizeof(*it));
398         break;
399
400         /*
401          * SET requests.  Should only get here if registered RWRITE 
402          */
403     case MODE_SET_RESERVE1:
404         if (requests->requestvb->type != ASN_INTEGER)
405             netsnmp_set_request_error(reqinfo, requests,
406                                       SNMP_ERR_WRONGTYPE);
407         break;
408
409     case MODE_SET_RESERVE2:
410         /*
411          * store old info for undo later 
412          */
413         memdup((u_char **) & it_save, (u_char *) it, sizeof(u_long));
414         if (it_save == NULL) {
415             netsnmp_set_request_error(reqinfo, requests,
416                                       SNMP_ERR_RESOURCEUNAVAILABLE);
417             return SNMP_ERR_NOERROR;
418         }
419         netsnmp_request_add_list_data(requests,
420                                       netsnmp_create_data_list
421                                       (INSTANCE_HANDLER_NAME, it_save,
422                                        free));
423         break;
424
425     case MODE_SET_ACTION:
426         /*
427          * update current 
428          */
429         DEBUGMSGTL(("testhandler", "updated int %d -> %l\n", *it,
430                     *(requests->requestvb->val.integer)));
431         *it = (int) *(requests->requestvb->val.integer);
432         break;
433
434     case MODE_SET_UNDO:
435         *it =
436             *((u_int *) netsnmp_request_get_list_data(requests,
437                                                       INSTANCE_HANDLER_NAME));
438         break;
439
440     case MODE_SET_COMMIT:
441     case MODE_SET_FREE:
442         /*
443          * nothing to do 
444          */
445         break;
446     }
447     if (handler->next && handler->next->access_method)
448         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
449                                          requests);
450     return SNMP_ERR_NOERROR;
451 }
452
453 int
454 netsnmp_instance_helper_handler(netsnmp_mib_handler *handler,
455                                 netsnmp_handler_registration *reginfo,
456                                 netsnmp_agent_request_info *reqinfo,
457                                 netsnmp_request_info *requests)
458 {
459
460     netsnmp_variable_list *var = requests->requestvb;
461
462     int             ret, cmp;
463
464     DEBUGMSGTL(("helper:instance", "Got request:\n"));
465     cmp = snmp_oid_compare(requests->requestvb->name,
466                            requests->requestvb->name_length,
467                            reginfo->rootoid, reginfo->rootoid_len);
468
469     DEBUGMSGTL(("helper:instance", "  oid:", cmp));
470     DEBUGMSGOID(("helper:instance", var->name, var->name_length));
471     DEBUGMSG(("helper:instance", "\n"));
472
473     switch (reqinfo->mode) {
474     case MODE_GET:
475         if (cmp != 0) {
476             netsnmp_set_request_error(reqinfo, requests,
477                                       SNMP_NOSUCHINSTANCE);
478             return SNMP_ERR_NOERROR;
479         } else {
480             return netsnmp_call_next_handler(handler, reginfo, reqinfo,
481                                              requests);
482         }
483         break;
484
485     case MODE_SET_RESERVE1:
486     case MODE_SET_RESERVE2:
487     case MODE_SET_ACTION:
488     case MODE_SET_COMMIT:
489     case MODE_SET_UNDO:
490     case MODE_SET_FREE:
491         if (cmp != 0) {
492             netsnmp_set_request_error(reqinfo, requests,
493                                       SNMP_ERR_NOCREATION);
494             return SNMP_ERR_NOERROR;
495         } else {
496             return netsnmp_call_next_handler(handler, reginfo, reqinfo,
497                                              requests);
498         }
499         break;
500
501     case MODE_GETNEXT:
502         if (cmp < 0 || (cmp == 0 && requests->inclusive)) {
503             reqinfo->mode = MODE_GET;
504             snmp_set_var_objid(requests->requestvb, reginfo->rootoid,
505                                reginfo->rootoid_len);
506             ret =
507                 netsnmp_call_next_handler(handler, reginfo, reqinfo,
508                                           requests);
509             reqinfo->mode = MODE_GETNEXT;
510             return ret;
511         } else {
512             return SNMP_ERR_NOERROR;
513         }
514         break;
515     }
516     /*
517      * got here only if illegal mode found 
518      */
519     return SNMP_ERR_GENERR;
520 }
521
522 /*
523  * @} 
524  */