and added files
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / header_complex.c
1 #ifdef BRCM_SNMP_NOT_USED
2 /*
3  * header complex:  More complex storage and data sorting for mib modules 
4  */
5
6 #include <net-snmp/net-snmp-config.h>
7
8 #include <sys/types.h>
9 #if HAVE_WINSOCK_H
10 #include <winsock.h>
11 #endif
12 #if HAVE_STDLIB_H
13 #include <stdlib.h>
14 #endif
15 #if HAVE_STRING_H
16 #include <string.h>
17 #else
18 #include <strings.h>
19 #endif
20
21 #include <net-snmp/net-snmp-includes.h>
22 #include <net-snmp/agent/net-snmp-agent-includes.h>
23 #include "header_complex.h"
24
25 int
26 header_complex_generate_varoid(netsnmp_variable_list * var)
27 {
28     int             i;
29
30     if (var->name == NULL) {
31         /*
32          * assume cached value is correct 
33          */
34         switch (var->type) {
35         case ASN_INTEGER:
36         case ASN_COUNTER:
37         case ASN_GAUGE:
38         case ASN_TIMETICKS:
39             var->name_length = 1;
40             var->name = (oid *) malloc(sizeof(oid));
41             if (var->name == NULL)
42                 return SNMPERR_GENERR;
43             var->name[0] = *(var->val.integer);
44             break;
45
46         case ASN_PRIV_IMPLIED_OBJECT_ID:
47             var->name_length = var->val_len / sizeof(oid);
48             var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
49             if (var->name == NULL)
50                 return SNMPERR_GENERR;
51
52             for (i = 0; i < (int) var->name_length; i++)
53                 var->name[i] = var->val.objid[i];
54             break;
55
56         case ASN_OBJECT_ID:
57             var->name_length = var->val_len / sizeof(oid) + 1;
58             var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
59             if (var->name == NULL)
60                 return SNMPERR_GENERR;
61
62             var->name[0] = var->name_length - 1;
63             for (i = 0; i < (int) var->name_length - 1; i++)
64                 var->name[i + 1] = var->val.objid[i];
65             break;
66
67         case ASN_PRIV_IMPLIED_OCTET_STR:
68             var->name_length = var->val_len;
69             var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
70             if (var->name == NULL)
71                 return SNMPERR_GENERR;
72
73             for (i = 0; i < (int) var->val_len; i++)
74                 var->name[i] = (oid) var->val.string[i];
75             break;
76
77         case ASN_OPAQUE:
78         case ASN_OCTET_STR:
79             var->name_length = var->val_len + 1;
80             var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
81             if (var->name == NULL)
82                 return SNMPERR_GENERR;
83
84             var->name[0] = (oid) var->val_len;
85             for (i = 0; i < (int) var->val_len; i++)
86                 var->name[i + 1] = (oid) var->val.string[i];
87             break;
88
89         default:
90             DEBUGMSGTL(("header_complex_generate_varoid",
91                         "invalid asn type: %d\n", var->type));
92             return SNMPERR_GENERR;
93         }
94     }
95     if (var->name_length > MAX_OID_LEN) {
96         DEBUGMSGTL(("header_complex_generate_varoid",
97                     "Something terribly wrong, namelen = %d\n",
98                     var->name_length));
99         return SNMPERR_GENERR;
100     }
101
102     return SNMPERR_SUCCESS;
103 }
104
105 /*
106  * header_complex_parse_oid(): parses an index to the usmTable to
107  * break it down into a engineID component and a name component.
108  * The results are stored in the data pointer, as a varbindlist:
109  * 
110  * 
111  * returns 1 if an error is encountered, or 0 if successful.
112  */
113 int
114 header_complex_parse_oid(oid * oidIndex, size_t oidLen,
115                          netsnmp_variable_list * data)
116 {
117     netsnmp_variable_list *var = data;
118     int             i, itmp;
119
120     while (var && oidLen > 0) {
121         switch (var->type) {
122         case ASN_INTEGER:
123         case ASN_COUNTER:
124         case ASN_GAUGE:
125         case ASN_TIMETICKS:
126             var->val.integer = (long *) calloc(1, sizeof(long));
127             if (var->val.string == NULL)
128                 return SNMPERR_GENERR;
129
130             *var->val.integer = (long) *oidIndex++;
131             var->val_len = sizeof(long);
132             oidLen--;
133             DEBUGMSGTL(("header_complex_parse_oid",
134                         "Parsed int(%d): %d\n", var->type,
135                         *var->val.integer));
136             break;
137
138         case ASN_OBJECT_ID:
139         case ASN_PRIV_IMPLIED_OBJECT_ID:
140             if (var->type == ASN_PRIV_IMPLIED_OBJECT_ID) {
141                 itmp = oidLen;
142             } else {
143                 itmp = (long) *oidIndex++;
144                 oidLen--;
145                 if (itmp > (int) oidLen)
146                     return SNMPERR_GENERR;
147             }
148
149             if (itmp == 0)
150                 break;          /* zero length strings shouldn't malloc */
151
152             var->val_len = itmp * sizeof(oid);
153             var->val.objid = (oid *) calloc(1, var->val_len);
154             if (var->val.objid == NULL)
155                 return SNMPERR_GENERR;
156
157             for (i = 0; i < itmp; i++)
158                 var->val.objid[i] = (u_char) * oidIndex++;
159             oidLen -= itmp;
160
161             DEBUGMSGTL(("header_complex_parse_oid", "Parsed oid: "));
162             DEBUGMSGOID(("header_complex_parse_oid", var->val.objid,
163                          var->val_len / sizeof(oid)));
164             DEBUGMSG(("header_complex_parse_oid", "\n"));
165             break;
166
167         case ASN_OPAQUE:
168         case ASN_OCTET_STR:
169         case ASN_PRIV_IMPLIED_OCTET_STR:
170             if (var->type == ASN_PRIV_IMPLIED_OCTET_STR) {
171                 itmp = oidLen;
172             } else {
173                 itmp = (long) *oidIndex++;
174                 oidLen--;
175                 if (itmp > (int) oidLen)
176                     return SNMPERR_GENERR;
177             }
178
179             if (itmp == 0)
180                 break;          /* zero length strings shouldn't malloc */
181
182             /*
183              * malloc by size+1 to allow a null to be appended. 
184              */
185             var->val_len = itmp;
186             var->val.string = (u_char *) calloc(1, itmp + 1);
187             if (var->val.string == NULL)
188                 return SNMPERR_GENERR;
189
190             for (i = 0; i < itmp; i++)
191                 var->val.string[i] = (u_char) * oidIndex++;
192             var->val.string[itmp] = '\0';
193             oidLen -= itmp;
194
195             DEBUGMSGTL(("header_complex_parse_oid",
196                         "Parsed str(%d): %s\n", var->type,
197                         var->val.string));
198             break;
199
200         default:
201             DEBUGMSGTL(("header_complex_parse_oid",
202                         "invalid asn type: %d\n", var->type));
203             return SNMPERR_GENERR;
204         }
205         var = var->next_variable;
206     }
207     if (var != NULL || oidLen > 0)
208         return SNMPERR_GENERR;
209     return SNMPERR_SUCCESS;
210 }
211
212
213 void
214 header_complex_generate_oid(oid * name, /* out */
215                             size_t * length,    /* out */
216                             oid * prefix,
217                             size_t prefix_len,
218                             netsnmp_variable_list * data)
219 {
220
221     oid            *oidptr;
222     netsnmp_variable_list *var;
223
224     if (prefix) {
225         memcpy(name, prefix, prefix_len * sizeof(oid));
226         oidptr = (name + (prefix_len));
227         *length = prefix_len;
228     } else {
229         oidptr = name;
230         *length = 0;
231     }
232
233     for (var = data; var != NULL; var = var->next_variable) {
234         header_complex_generate_varoid(var);
235         memcpy(oidptr, var->name, sizeof(oid) * var->name_length);
236         oidptr = oidptr + var->name_length;
237         *length += var->name_length;
238     }
239
240     DEBUGMSGTL(("header_complex_generate_oid", "generated: "));
241     DEBUGMSGOID(("header_complex_generate_oid", name, *length));
242     DEBUGMSG(("header_complex_generate_oid", "\n"));
243 }
244
245 /*
246  * finds the data in "datalist" stored at "index" 
247  */
248 void           *
249 header_complex_get(struct header_complex_index *datalist,
250                    netsnmp_variable_list * index)
251 {
252     oid             searchfor[MAX_OID_LEN];
253     size_t          searchfor_len;
254
255     header_complex_generate_oid(searchfor,      /* out */
256                                 &searchfor_len, /* out */
257                                 NULL, 0, index);
258     return header_complex_get_from_oid(datalist, searchfor, searchfor_len);
259 }
260
261 void           *
262 header_complex_get_from_oid(struct header_complex_index *datalist,
263                             oid * searchfor, size_t searchfor_len)
264 {
265     struct header_complex_index *nptr;
266     for (nptr = datalist; nptr != NULL; nptr = nptr->next) {
267         if (netsnmp_oid_equals(searchfor, searchfor_len,
268                              nptr->name, nptr->namelen) == 0)
269             return nptr->data;
270     }
271     return NULL;
272 }
273
274
275 void           *
276 header_complex(struct header_complex_index *datalist,
277                struct variable *vp,
278                oid * name,
279                size_t * length,
280                int exact, size_t * var_len, WriteMethod ** write_method)
281 {
282
283     struct header_complex_index *nptr, *found = NULL;
284     oid             indexOid[MAX_OID_LEN];
285     size_t          len;
286     int             result;
287
288     /*
289      * set up some nice defaults for the user 
290      */
291     if (write_method)
292         *write_method = NULL;
293     if (var_len)
294         *var_len = sizeof(long);
295
296     for (nptr = datalist; nptr != NULL && found == NULL; nptr = nptr->next) {
297         if (vp) {
298             memcpy(indexOid, vp->name, vp->namelen * sizeof(oid));
299             memcpy(indexOid + vp->namelen, nptr->name,
300                    nptr->namelen * sizeof(oid));
301             len = vp->namelen + nptr->namelen;
302         } else {
303             memcpy(indexOid, nptr->name, nptr->namelen * sizeof(oid));
304             len = nptr->namelen;
305         }
306         result = snmp_oid_compare(name, *length, indexOid, len);
307         DEBUGMSGTL(("header_complex", "Checking: "));
308         DEBUGMSGOID(("header_complex", indexOid, len));
309         DEBUGMSG(("header_complex", "\n"));
310
311         if (exact) {
312             if (result == 0) {
313                 found = nptr;
314             }
315         } else {
316             if (result == 0) {
317                 /*
318                  * found an exact match.  Need the next one for !exact 
319                  */
320                 if (nptr->next)
321                     found = nptr->next;
322             } else if (result == -1) {
323                 found = nptr;
324             }
325         }
326     }
327     if (found) {
328         if (vp) {
329             memcpy(name, vp->name, vp->namelen * sizeof(oid));
330             memcpy(name + vp->namelen, found->name,
331                    found->namelen * sizeof(oid));
332             *length = vp->namelen + found->namelen;
333         } else {
334             memcpy(name, found->name, found->namelen * sizeof(oid));
335             *length = found->namelen;
336         }
337         return found->data;
338     }
339
340     return NULL;
341 }
342
343 struct header_complex_index *
344 header_complex_add_data(struct header_complex_index **thedata,
345                         netsnmp_variable_list * var, void *data)
346 {
347     oid             newoid[MAX_OID_LEN];
348     size_t          newoid_len;
349     struct header_complex_index *ret;
350
351     if (thedata == NULL || var == NULL || data == NULL)
352         return NULL;
353
354     header_complex_generate_oid(newoid, &newoid_len, NULL, 0, var);
355     ret =
356         header_complex_add_data_by_oid(thedata, newoid, newoid_len, data);
357     /*
358      * free the variable list, but not the enclosed data!  it's not ours! 
359      */
360     snmp_free_varbind(var);
361     return (ret);
362 }
363
364 struct header_complex_index *
365 header_complex_add_data_by_oid(struct header_complex_index **thedata,
366                                oid * newoid, size_t newoid_len, void *data)
367 {
368     struct header_complex_index *hciptrn, *hciptrp, *ourself;
369
370     if (thedata == NULL || newoid == NULL || data == NULL)
371         return NULL;
372
373     for (hciptrn = *thedata, hciptrp = NULL;
374          hciptrn != NULL; hciptrp = hciptrn, hciptrn = hciptrn->next)
375         /*
376          * XXX: check for == and error (overlapping table entries) 
377          */
378         if (snmp_oid_compare
379             (hciptrn->name, hciptrn->namelen, newoid, newoid_len)
380             > 0)
381             break;
382
383     /*
384      * nptr should now point to the spot that we need to add ourselves
385      * in front of, and pptr should be our new 'prev'. 
386      */
387
388     /*
389      * create ourselves 
390      */
391     ourself = (struct header_complex_index *)
392         SNMP_MALLOC_STRUCT(header_complex_index);
393
394     /*
395      * change our pointers 
396      */
397     ourself->prev = hciptrp;
398     ourself->next = hciptrn;
399
400     if (ourself->next)
401         ourself->next->prev = ourself;
402
403     if (ourself->prev)
404         ourself->prev->next = ourself;
405
406     ourself->data = data;
407     ourself->name = snmp_duplicate_objid(newoid, newoid_len);
408     ourself->namelen = newoid_len;
409
410     /*
411      * rewind to the head of the list and return it (since the new head
412      * could be us, we need to notify the above routine who the head now is. 
413      */
414     for (hciptrp = ourself; hciptrp->prev != NULL;
415          hciptrp = hciptrp->prev);
416
417     *thedata = hciptrp;
418     DEBUGMSGTL(("header_complex_add_data", "adding something...\n"));
419
420     return hciptrp;
421 }
422
423 /*
424  * extracts an entry from the storage space (removing it from future
425  * accesses) and returns the data stored there
426  * 
427  * Modifies "thetop" pointer as needed (and if present) if were
428  * extracting the first node.
429  */
430
431 void           *
432 header_complex_extract_entry(struct header_complex_index **thetop,
433                              struct header_complex_index *thespot)
434 {
435     struct header_complex_index *hciptrp, *hciptrn;
436     void           *retdata = thespot->data;
437
438     if (thespot == NULL) {
439         DEBUGMSGTL(("header_complex_extract_entry",
440                     "Null pointer asked to be extracted\n"));
441         return NULL;
442     }
443
444     hciptrp = thespot->prev;
445     hciptrn = thespot->next;
446
447     if (hciptrp)
448         hciptrp->next = hciptrn;
449     else if (thetop)
450         *thetop = hciptrn;
451
452     if (hciptrn)
453         hciptrn->prev = hciptrp;
454
455     if (thespot->name)
456         free(thespot->name);
457
458     free(thespot);
459     return retdata;
460 }
461
462 /*
463  * wipe out a single entry 
464  */
465 void
466 header_complex_free_entry(struct header_complex_index *theentry,
467                           HeaderComplexCleaner * cleaner)
468 {
469     void           *data;
470     data = header_complex_extract_entry(NULL, theentry);
471     (*cleaner) (data);
472 }
473
474 /*
475  * completely wipe out all entries in our data store 
476  */
477 void
478 header_complex_free_all(struct header_complex_index *thestuff,
479                         HeaderComplexCleaner * cleaner)
480 {
481     struct header_complex_index *hciptr, *hciptrn;
482
483     for (hciptr = thestuff; hciptr != NULL; hciptr = hciptrn) {
484         hciptrn = hciptr->next; /* need to extract this before deleting it */
485         header_complex_free_entry(hciptr, cleaner);
486     }
487 }
488
489 struct header_complex_index *
490 header_complex_find_entry(struct header_complex_index *thestuff,
491                           void *theentry)
492 {
493     struct header_complex_index *hciptr;
494
495     for (hciptr = thestuff; hciptr != NULL && hciptr->data != theentry;
496          hciptr = hciptr->next);
497     return hciptr;
498 }
499
500 #ifdef TESTING
501
502 void
503 header_complex_dump(struct header_complex_index *thestuff)
504 {
505     struct header_complex_index *hciptr;
506     oid             oidsave[MAX_OID_LEN];
507     size_t          len;
508
509     for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
510         DEBUGMSGTL(("header_complex_dump", "var:  "));
511         header_complex_generate_oid(oidsave, &len, NULL, 0, hciptr->);
512         DEBUGMSGOID(("header_complex_dump", oidsave, len));
513         DEBUGMSG(("header_complex_dump", "\n"));
514     }
515 }
516
517 main()
518 {
519     oid             oidsave[MAX_OID_LEN];
520     int             len = MAX_OID_LEN, len2;
521     netsnmp_variable_list *vars;
522     long            ltmp = 4242, ltmp2 = 88, ltmp3 = 1, ltmp4 = 4200;
523     oid             ourprefix[] = { 1, 2, 3, 4 };
524     oid             testparse[] = { 4, 116, 101, 115, 116, 4200 };
525     int             ret;
526
527     char           *string = "wes", *string2 = "dawn", *string3 = "test";
528
529     struct header_complex_index *thestorage = NULL;
530
531     debug_register_tokens("header_complex");
532     snmp_set_do_debugging(1);
533
534     vars = NULL;
535     len2 = sizeof(ltmp);
536     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp,
537                               len2);
538     header_complex_add_data(&thestorage, vars, ourprefix);
539
540     vars = NULL;
541     len2 = strlen(string);
542     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string, len2);
543     header_complex_add_data(&thestorage, vars, ourprefix);
544
545     vars = NULL;
546     len2 = sizeof(ltmp2);
547     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp2,
548                               len2);
549     header_complex_add_data(&thestorage, vars, ourprefix);
550
551     vars = NULL;
552     len2 = strlen(string2);
553     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string2,
554                               len2);
555     header_complex_add_data(&thestorage, vars, ourprefix);
556
557     vars = NULL;
558     len2 = sizeof(ltmp3);
559     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp3,
560                               len2);
561     header_complex_add_data(&thestorage, vars, ourprefix);
562
563     vars = NULL;
564     len2 = strlen(string3);
565     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string3,
566                               len2);
567     len2 = sizeof(ltmp4);
568     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp4,
569                               len2);
570     header_complex_add_data(&thestorage, vars, ourprefix);
571
572     header_complex_dump(thestorage);
573
574     vars = NULL;
575     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0);
576     snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, NULL, 0);
577     ret =
578         header_complex_parse_oid(testparse,
579                                  sizeof(testparse) / sizeof(oid), vars);
580     DEBUGMSGTL(("header_complex_test", "parse returned %d...\n", ret));
581
582 }
583 #endif
584
585 #endif /* #if BRCM_SNMP_NOT_USED */