Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / net-snmp / agent / helpers / old_api.c
1 #include <net-snmp/net-snmp-config.h>
2
3 #if HAVE_STRING_H
4 #include <string.h>
5 #else
6 #include <strings.h>
7 #endif
8
9 #include <net-snmp/net-snmp-includes.h>
10 #include <net-snmp/agent/net-snmp-agent-includes.h>
11
12 #include <net-snmp/agent/old_api.h>
13 #include <net-snmp/agent/agent_callbacks.h>
14
15 #if HAVE_DMALLOC_H
16 #include <dmalloc.h>
17 #endif
18
19 #define MIB_CLIENTS_ARE_EVIL 1
20
21 /*
22  * don't use these! 
23  */
24 void            set_current_agent_session(netsnmp_agent_session *asp);
25 netsnmp_agent_session *netsnmp_get_current_agent_session(void);
26
27 /** @defgroup old_api old_api: Calls mib module code written in the old style of code.
28  *  @ingroup handler
29  *  This is a backwards compatilibity module that allows code written
30  *  in the old API to be run under the new handler based architecture.
31  *  Use it by calling netsnmp_register_old_api().
32  *  @{
33  */
34
35 /** returns a old_api handler that should be the final calling
36  * handler.  Don't use this function.  Use the netsnmp_register_old_api()
37  * function instead.
38  */
39 netsnmp_mib_handler *
40 get_old_api_handler(void)
41 {
42     return netsnmp_create_handler("old_api", netsnmp_old_api_helper);
43 }
44
45
46 /** Registers an old API set into the mib tree.  Functionally this
47  * mimics the old register_mib_context() function (and in fact the new
48  * register_mib_context() function merely calls this new old_api one).
49  */
50 int
51 netsnmp_register_old_api(const char *moduleName,
52                          struct variable *var,
53                          size_t varsize,
54                          size_t numvars,
55                          oid * mibloc,
56                          size_t mibloclen,
57                          int priority,
58                          int range_subid,
59                          oid range_ubound,
60                          netsnmp_session * ss,
61                          const char *context, int timeout, int flags)
62 {
63
64     netsnmp_old_api_info *old_info =
65         SNMP_MALLOC_TYPEDEF(netsnmp_old_api_info);
66     unsigned int    i;
67
68     old_info->var = var;
69     old_info->varsize = varsize;
70     old_info->numvars = numvars;
71     old_info->ss = ss;
72     old_info->flags = flags;
73
74     /*
75      * register all subtree nodes 
76      */
77     for (i = 0; i < numvars; i++) {
78         struct variable *vp;
79         netsnmp_handler_registration *reginfo =
80             SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration);
81
82         memdup((void *) &vp,
83                (void *) (struct variable *) ((char *) var + varsize * i),
84                varsize);
85
86         reginfo->handler = get_old_api_handler();
87         reginfo->handlerName = strdup(moduleName);
88         reginfo->rootoid_len = (mibloclen + vp->namelen);
89         reginfo->rootoid =
90             (oid *) malloc(reginfo->rootoid_len * sizeof(oid));
91
92         memcpy(reginfo->rootoid, mibloc, mibloclen * sizeof(oid));
93         memcpy(reginfo->rootoid + mibloclen, vp->name, vp->namelen
94                * sizeof(oid));
95         reginfo->handler->myvoid = (void *) vp;
96
97         reginfo->priority = priority;
98         reginfo->range_subid = range_subid;
99
100         reginfo->range_ubound = range_ubound;
101         reginfo->timeout = timeout;
102         reginfo->contextName = (context) ? strdup(context) : NULL;
103         reginfo->modes = HANDLER_CAN_RWRITE;
104
105         /*
106          * register ourselves in the mib tree 
107          */
108         if (netsnmp_register_handler(reginfo) != MIB_REGISTERED_OK) {
109             netsnmp_handler_registration_free(reginfo);
110             SNMP_FREE(vp);
111         }
112     }
113     SNMP_FREE(old_info);
114     return SNMPERR_SUCCESS;
115 }
116
117 /** registers a row within a mib table */
118 int
119 netsnmp_register_mib_table_row(const char *moduleName,
120                                struct variable *var,
121                                size_t varsize,
122                                size_t numvars,
123                                oid * mibloc,
124                                size_t mibloclen,
125                                int priority,
126                                int var_subid,
127                                netsnmp_session * ss,
128                                const char *context, int timeout, int flags)
129 {
130     unsigned int    i = 0, rc = 0;
131     oid             ubound = 0;
132
133     for (i = 0; i < numvars; i++) {
134         struct variable *vr =
135             (struct variable *) ((char *) var + (i * varsize));
136         netsnmp_handler_registration *r =
137             SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration);
138
139         if (r == NULL) {
140             /*
141              * Unregister whatever we have registered so far, and
142              * return an error.  
143              */
144             rc = MIB_REGISTRATION_FAILED;
145             break;
146         }
147         memset(r, 0, sizeof(netsnmp_handler_registration));
148
149         r->handler = get_old_api_handler();
150         r->handlerName = strdup(moduleName);
151
152         if (r->handlerName == NULL) {
153             netsnmp_handler_registration_free(r);
154             break;
155         }
156
157         r->rootoid_len = mibloclen;
158         r->rootoid = (oid *) malloc(r->rootoid_len * sizeof(oid));
159
160         if (r->rootoid == NULL) {
161             netsnmp_handler_registration_free(r);
162             rc = MIB_REGISTRATION_FAILED;
163             break;
164         }
165         memcpy(r->rootoid, mibloc, mibloclen * sizeof(oid));
166         memcpy((u_char *) (r->rootoid + (var_subid - 1)), vr->name,
167                vr->namelen * sizeof(oid));
168         DEBUGMSGTL(("netsnmp_register_mib_table_row", "rootoid "));
169         DEBUGMSGOID(("netsnmp_register_mib_table_row", r->rootoid,
170                      r->rootoid_len));
171         DEBUGMSG(("netsnmp_register_mib_table_row", "\n"));
172         r->handler->myvoid = (void *) malloc(varsize);
173
174         if (r->handler->myvoid == NULL) {
175             netsnmp_handler_registration_free(r);
176             rc = MIB_REGISTRATION_FAILED;
177             break;
178         }
179         memcpy((char *) r->handler->myvoid, vr, varsize);
180
181         r->contextName = (context) ? strdup(context) : NULL;
182
183         if (context != NULL && r->contextName == NULL) {
184             netsnmp_handler_registration_free(r);
185             rc = MIB_REGISTRATION_FAILED;
186             break;
187         }
188
189         r->priority = priority;
190         r->range_subid = 0;     /* var_subid; */
191         r->range_ubound = 0;    /* range_ubound; */
192         r->timeout = timeout;
193         r->modes = HANDLER_CAN_RWRITE;
194
195         /*
196          * Register this column and row  
197          */
198         if ((rc =
199              netsnmp_register_handler_nocallback(r)) !=
200             MIB_REGISTERED_OK) {
201             DEBUGMSGTL(("netsnmp_register_mib_table_row",
202                         "register failed %d\n", rc));
203             netsnmp_handler_registration_free(r);
204             break;
205         }
206
207         if (vr->namelen > 0) {
208             if (vr->name[vr->namelen - 1] > ubound) {
209                 ubound = vr->name[vr->namelen - 1];
210             }
211         }
212     }
213
214     if (rc == MIB_REGISTERED_OK) {
215         struct register_parameters reg_parms;
216
217         reg_parms.name = mibloc;
218         reg_parms.namelen = mibloclen;
219         reg_parms.priority = priority;
220         reg_parms.flags = (u_char) flags;
221         reg_parms.range_subid = var_subid;
222         reg_parms.range_ubound = ubound;
223         reg_parms.timeout = timeout;
224         rc = snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
225                                  SNMPD_CALLBACK_REGISTER_OID, &reg_parms);
226     }
227
228     return rc;
229 }
230
231 /** implements the old_api handler */
232 int
233 netsnmp_old_api_helper(netsnmp_mib_handler *handler,
234                        netsnmp_handler_registration *reginfo,
235                        netsnmp_agent_request_info *reqinfo,
236                        netsnmp_request_info *requests)
237 {
238
239 #if MIB_CLIENTS_ARE_EVIL
240     oid             save[MAX_OID_LEN];
241     size_t          savelen = 0;
242 #endif
243     struct variable compat_var, *cvp = &compat_var;
244     int             exact = 1;
245     int             status;
246
247     struct variable *vp;
248     WriteMethod    *write_method = NULL;
249     size_t          len;
250     u_char         *access = NULL;
251     netsnmp_old_api_cache *cacheptr;
252     netsnmp_agent_session *oldasp = NULL;
253
254     vp = (struct variable *) handler->myvoid;
255
256     /*
257      * create old variable structure with right information 
258      */
259     memcpy(cvp->name, reginfo->rootoid,
260            reginfo->rootoid_len * sizeof(oid));
261     cvp->namelen = reginfo->rootoid_len;
262     cvp->type = vp->type;
263     cvp->magic = vp->magic;
264     cvp->acl = vp->acl;
265     cvp->findVar = vp->findVar;
266
267     switch (reqinfo->mode) {
268     case MODE_GETNEXT:
269     case MODE_GETBULK:
270         exact = 0;
271     }
272
273     for (; requests; requests = requests->next) {
274
275 #if MIB_CLIENTS_ARE_EVIL
276         savelen = requests->requestvb->name_length;
277         memcpy(save, requests->requestvb->name, savelen * sizeof(oid));
278 #endif
279
280         switch (reqinfo->mode) {
281         case MODE_GET:
282         case MODE_GETNEXT:
283         case MODE_SET_RESERVE1:
284             /*
285              * Actually call the old mib-module function 
286              */
287             if (vp && vp->findVar)
288                 access = (*(vp->findVar)) (cvp, requests->requestvb->name,
289                                            &(requests->requestvb->
290                                              name_length), exact, &len,
291                                            &write_method);
292             else
293                 access = NULL;
294
295 #ifdef WWW_FIX
296             if (IS_DELEGATED(cvp->type)) {
297                 add_method = (AddVarMethod *) statP;
298                 requests->delayed = 1;
299                 have_delegated = 1;
300                 continue;       /* WWW: This may not get to the right place */
301             }
302 #endif
303
304             /*
305              * WWW: end range checking 
306              */
307             if (access) {
308                 /*
309                  * result returned 
310                  */
311                 if (reqinfo->mode != MODE_SET_RESERVE1)
312                     snmp_set_var_typed_value(requests->requestvb,
313                                              cvp->type, access, len);
314             } else {
315                 /*
316                  * no result returned 
317                  */
318 #if MIB_CLIENTS_ARE_EVIL
319                 if (access == NULL) {
320                     if (netsnmp_oid_equals(requests->requestvb->name,
321                                          requests->requestvb->name_length,
322                                          save, savelen) != 0) {
323                         DEBUGMSGTL(("old_api", "evil_client: %s\n",
324                                     reginfo->handlerName));
325                         memcpy(requests->requestvb->name, save,
326                                savelen * sizeof(oid));
327                         requests->requestvb->name_length = savelen;
328                     }
329                 }
330 #endif
331             }
332
333             /*
334              * AAA: fall through for everything that is a set (see BBB) 
335              */
336             if (reqinfo->mode != MODE_SET_RESERVE1)
337                 break;
338
339             cacheptr = SNMP_MALLOC_TYPEDEF(netsnmp_old_api_cache);
340             if (!cacheptr)
341                 return netsnmp_set_request_error(reqinfo, requests,
342                                                  SNMP_ERR_RESOURCEUNAVAILABLE);
343             cacheptr->data = access;
344             cacheptr->write_method = write_method;
345             netsnmp_request_add_list_data(requests,
346                                           netsnmp_create_data_list
347                                           (OLD_API_NAME, cacheptr, free));
348             /*
349              * BBB: fall through for everything that is a set (see AAA) 
350              */
351
352         default:
353             /*
354              * WWW: explicitly list the SET conditions 
355              */
356             /*
357              * (the rest of the) SET contions 
358              */
359             cacheptr =
360                 (netsnmp_old_api_cache *)
361                 netsnmp_request_get_list_data(requests, OLD_API_NAME);
362
363             if (cacheptr == NULL || cacheptr->write_method == NULL) {
364                 /*
365                  * WWW: try to set ourselves if possible? 
366                  */
367                 return netsnmp_set_request_error(reqinfo, requests,
368                                                  SNMP_ERR_NOTWRITABLE);
369             }
370
371             oldasp = netsnmp_get_current_agent_session();
372             set_current_agent_session(reqinfo->asp);
373             status =
374                 (*(cacheptr->write_method)) (reqinfo->mode,
375                                              requests->requestvb->val.
376                                              string,
377                                              requests->requestvb->type,
378                                              requests->requestvb->val_len,
379                                              cacheptr->data,
380                                              requests->requestvb->name,
381                                              requests->requestvb->
382                                              name_length);
383             set_current_agent_session(oldasp);
384
385             if (status != SNMP_ERR_NOERROR) {
386                 netsnmp_set_request_error(reqinfo, requests, status);
387             }
388
389             /*
390              * clean up is done by the automatic freeing of the
391              * cache stored in the request. 
392              */
393
394             break;
395         }
396     }
397     return SNMP_ERR_NOERROR;
398 }
399
400 /** @} */
401
402 /*
403  * don't use this! 
404  */
405 static netsnmp_agent_session *current_agent_session = NULL;
406 netsnmp_agent_session *
407 netsnmp_get_current_agent_session()
408 {
409     return current_agent_session;
410 }
411
412 /*
413  * don't use this! 
414  */
415 void
416 set_current_agent_session(netsnmp_agent_session *asp)
417 {
418     current_agent_session = asp;
419 }