# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / net-snmp / agent / agent_index.c
1 /*
2  * agent_index.c
3  *
4  * Maintain a registry of index allocations
5  *      (Primarily required for AgentX support,
6  *       but it could be more widely useable).
7  */
8
9
10 #include <net-snmp/net-snmp-config.h>
11 #include <signal.h>
12 #if HAVE_STRING_H
13 #include <string.h>
14 #endif
15 #if HAVE_STDLIB_H
16 #include <stdlib.h>
17 #endif
18 #include <sys/types.h>
19 #include <stdio.h>
20 #include <fcntl.h>
21 #if HAVE_WINSOCK_H
22 #include <winsock.h>
23 #endif
24 #if TIME_WITH_SYS_TIME
25 # ifdef WIN32
26 #  include <sys/timeb.h>
27 # else
28 #  include <sys/time.h>
29 # endif
30 # include <time.h>
31 #else
32 # if HAVE_SYS_TIME_H
33 #  include <sys/time.h>
34 # else
35 #  include <time.h>
36 # endif
37 #endif
38 #if HAVE_NETINET_IN_H
39 #include <netinet/in.h>
40 #endif
41
42 #if HAVE_DMALLOC_H
43 #include <dmalloc.h>
44 #endif
45
46 #include <net-snmp/net-snmp-includes.h>
47 #include <net-snmp/agent/net-snmp-agent-includes.h>
48 #include <net-snmp/agent/agent_callbacks.h>
49 #include <net-snmp/agent/agent_index.h>
50
51 #include "snmpd.h"
52 #include "mibgroup/struct.h"
53 #include <net-snmp/agent/table.h>
54 #include <net-snmp/agent/table_iterator.h>
55 #include "mib_module_includes.h"
56
57 #ifdef USING_AGENTX_SUBAGENT_MODULE
58 #include "agentx/subagent.h"
59 #include "agentx/client.h"
60 #endif
61
62 #if defined(BRCM_SNMP_DEBUG) || !defined(BUILD_ILMI)
63
64         /*
65          * Initial support for index allocation
66          */
67
68 struct snmp_index {
69     netsnmp_variable_list *varbind;     /* or pointer to var_list ? */
70     int             allocated;
71     netsnmp_session *session;
72     struct snmp_index *next_oid;
73     struct snmp_index *prev_oid;
74     struct snmp_index *next_idx;
75 }              *snmp_index_head = NULL;
76 #endif
77
78 #ifndef BUILD_ILMI
79 extern netsnmp_session *main_session;
80
81 /*
82  * The caller is responsible for free()ing the memory returned by
83  * this function.  
84  */
85
86 char           *
87 register_string_index(oid * name, size_t name_len, char *cp)
88 {
89     netsnmp_variable_list varbind, *res;
90
91     memset(&varbind, 0, sizeof(netsnmp_variable_list));
92     varbind.type = ASN_OCTET_STR;
93     snmp_set_var_objid(&varbind, name, name_len);
94     if (cp != ANY_STRING_INDEX) {
95         snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
96         res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
97     } else {
98         res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
99     }
100
101     if (res == NULL) {
102         return NULL;
103     } else {
104         char           *rv = strdup(res->val.string);
105         free(res);
106         return rv;
107     }
108 }
109
110 int
111 register_int_index(oid * name, size_t name_len, int val)
112 {
113     netsnmp_variable_list varbind, *res;
114
115     memset(&varbind, 0, sizeof(netsnmp_variable_list));
116     varbind.type = ASN_INTEGER;
117     snmp_set_var_objid(&varbind, name, name_len);
118     varbind.val.string = varbind.buf;
119     if (val != ANY_INTEGER_INDEX) {
120         varbind.val_len = sizeof(long);
121         *varbind.val.integer = val;
122         res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
123     } else {
124         res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
125     }
126
127     if (res == NULL) {
128         return -1;
129     } else {
130         int             rv = *(res->val.integer);
131         free(res);
132         return rv;
133     }
134 }
135
136 /*
137  * The caller is responsible for free()ing the memory returned by
138  * this function.  
139  */
140
141 netsnmp_variable_list *
142 register_oid_index(oid * name, size_t name_len,
143                    oid * value, size_t value_len)
144 {
145     netsnmp_variable_list varbind;
146
147     memset(&varbind, 0, sizeof(netsnmp_variable_list));
148     varbind.type = ASN_OBJECT_ID;
149     snmp_set_var_objid(&varbind, name, name_len);
150     if (value != ANY_OID_INDEX) {
151         snmp_set_var_value(&varbind, (u_char *) value,
152                            value_len * sizeof(oid));
153         return register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
154     } else {
155         return register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
156     }
157 }
158
159 /*
160  * The caller is responsible for free()ing the memory returned by
161  * this function.  
162  */
163
164 netsnmp_variable_list *
165 register_index(netsnmp_variable_list * varbind, int flags,
166                netsnmp_session * ss)
167 {
168     netsnmp_variable_list *rv = NULL;
169     struct snmp_index *new_index, *idxptr, *idxptr2;
170     struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
171     int             res, res2, i;
172
173     DEBUGMSGTL(("register_index", "register "));
174     DEBUGMSGVAR(("register_index", varbind));
175     DEBUGMSG(("register_index", "for session %08p\n", ss));
176
177 #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
178     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
179                                NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
180         return (agentx_register_index(ss, varbind, flags));
181     }
182 #endif
183     /*
184      * Look for the requested OID entry 
185      */
186     prev_oid_ptr = NULL;
187     prev_idx_ptr = NULL;
188     res = 1;
189     res2 = 1;
190     for (idxptr = snmp_index_head; idxptr != NULL;
191          prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
192         if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
193                                     idxptr->varbind->name,
194                                     idxptr->varbind->name_length)) <= 0)
195             break;
196     }
197
198     /*
199      * Found the OID - now look at the registered indices 
200      */
201     if (res == 0 && idxptr) {
202         if (varbind->type != idxptr->varbind->type)
203             return NULL;        /* wrong type */
204
205         /*
206          * If we've been asked for an arbitrary new value,
207          *      then find the end of the list.
208          * If we've been asked for any arbitrary value,
209          *      then look for an unused entry, and use that.
210          *      If there aren't any, continue as for new.
211          * Otherwise, locate the given value in the (sorted)
212          *      list of already allocated values
213          */
214         if (flags & ALLOCATE_ANY_INDEX) {
215             for (idxptr2 = idxptr; idxptr2 != NULL;
216                  prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
217
218                 if (flags == ALLOCATE_ANY_INDEX && !(idxptr2->allocated)) {
219                     if ((rv =
220                          snmp_clone_varbind(idxptr2->varbind)) != NULL) {
221                         idxptr2->session = ss;
222                         idxptr2->allocated = 1;
223                     }
224                     return rv;
225                 }
226             }
227         } else {
228             for (idxptr2 = idxptr; idxptr2 != NULL;
229                  prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
230                 switch (varbind->type) {
231                 case ASN_INTEGER:
232                     res2 =
233                         (*varbind->val.integer -
234                          *idxptr2->varbind->val.integer);
235                     break;
236                 case ASN_OCTET_STR:
237                     i = SNMP_MIN(varbind->val_len,
238                                  idxptr2->varbind->val_len);
239                     res2 =
240                         memcmp(varbind->val.string,
241                                idxptr2->varbind->val.string, i);
242                     break;
243                 case ASN_OBJECT_ID:
244                     res2 =
245                         snmp_oid_compare(varbind->val.objid,
246                                          varbind->val_len / sizeof(oid),
247                                          idxptr2->varbind->val.objid,
248                                          idxptr2->varbind->val_len /
249                                          sizeof(oid));
250                     break;
251                 default:
252                     return NULL;        /* wrong type */
253                 }
254                 if (res2 <= 0)
255                     break;
256             }
257             if (res2 == 0) {
258                 if (idxptr2->allocated) {
259                     /*
260                      * No good: the index is in use.  
261                      */
262                     return NULL;
263                 } else {
264                     /*
265                      * Okay, it's unallocated, we can just claim ownership
266                      * here.  
267                      */
268                     if ((rv =
269                          snmp_clone_varbind(idxptr2->varbind)) != NULL) {
270                         idxptr2->session = ss;
271                         idxptr2->allocated = 1;
272                     }
273                     return rv;
274                 }
275             }
276         }
277     }
278
279     /*
280      * OK - we've now located where the new entry needs to
281      *      be fitted into the index registry tree          
282      * To recap:
283      *      'prev_oid_ptr' points to the head of the OID index
284      *          list prior to this one.  If this is null, then
285      *          it means that this is the first OID in the list.
286      *      'idxptr' points either to the head of this OID list,
287      *          or the next OID (if this is a new OID request)
288      *          These can be distinguished by the value of 'res'.
289      *
290      *      'prev_idx_ptr' points to the index entry that sorts
291      *          immediately prior to the requested value (if any).
292      *          If an arbitrary value is required, then this will
293      *          point to the last allocated index.
294      *          If this pointer is null, then either this is a new
295      *          OID request, or the requested value is the first
296      *          in the list.
297      *      'idxptr2' points to the next sorted index (if any)
298      *          but is not actually needed any more.
299      *
300      *  Clear?  Good!
301      *      I hope you've been paying attention.
302      *          There'll be a test later :-)
303      */
304
305     /*
306      *      We proceed by creating the new entry
307      *         (by copying the entry provided)
308      */
309     new_index = (struct snmp_index *) calloc(1, sizeof(struct snmp_index));
310     if (new_index == NULL)
311         return NULL;
312
313     if (0 == snmp_varlist_add_variable(&new_index->varbind,
314                                        varbind->name,
315                                        varbind->name_length,
316                                        varbind->type,
317                                        varbind->val.string,
318                                        varbind->val_len)) {
319         /*
320          * if (snmp_clone_var( varbind, new_index->varbind ) != 0 ) 
321          */
322         free(new_index);
323         return NULL;
324     }
325     new_index->session = ss;
326     new_index->allocated = 1;
327
328     if (varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX)
329         new_index->varbind->val.string[new_index->varbind->val_len] = 0;
330
331     /*
332      * If we've been given a value, then we can use that, but
333      *    otherwise, we need to create a new value for this entry.
334      * Note that ANY_INDEX and NEW_INDEX are both covered by this
335      *   test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?)
336      */
337     if (flags & ALLOCATE_ANY_INDEX) {
338         if (prev_idx_ptr) {
339             if (snmp_clone_var(prev_idx_ptr->varbind, new_index->varbind)
340                 != 0) {
341                 free(new_index);
342                 return NULL;
343             }
344         } else
345             new_index->varbind->val.string = new_index->varbind->buf;
346
347         switch (varbind->type) {
348         case ASN_INTEGER:
349             if (prev_idx_ptr) {
350                 (*new_index->varbind->val.integer)++;
351             } else
352                 *(new_index->varbind->val.integer) = 1;
353             new_index->varbind->val_len = sizeof(long);
354             break;
355         case ASN_OCTET_STR:
356             if (prev_idx_ptr) {
357                 i = new_index->varbind->val_len - 1;
358                 while (new_index->varbind->buf[i] == 'z') {
359                     new_index->varbind->buf[i] = 'a';
360                     i--;
361                     if (i < 0) {
362                         i = new_index->varbind->val_len;
363                         new_index->varbind->buf[i] = 'a';
364                         new_index->varbind->buf[i + 1] = 0;
365                     }
366                 }
367                 new_index->varbind->buf[i]++;
368             } else
369                 strcpy((char *) new_index->varbind->buf, "aaaa");
370             new_index->varbind->val_len =
371                 strlen((char *) new_index->varbind->buf);
372             break;
373         case ASN_OBJECT_ID:
374             if (prev_idx_ptr) {
375                 i = prev_idx_ptr->varbind->val_len / sizeof(oid) - 1;
376                 while (new_index->varbind->val.objid[i] == 255) {
377                     new_index->varbind->val.objid[i] = 1;
378                     i--;
379                     if (i == 0 && new_index->varbind->val.objid[0] == 2) {
380                         new_index->varbind->val.objid[0] = 1;
381                         i = new_index->varbind->val_len / sizeof(oid);
382                         new_index->varbind->val.objid[i] = 0;
383                         new_index->varbind->val_len += sizeof(oid);
384                     }
385                 }
386                 new_index->varbind->val.objid[i]++;
387             } else {
388                 /*
389                  * If the requested OID name is small enough,
390                  * *   append another OID (1) and use this as the
391                  * *   default starting value for new indexes.
392                  */
393                 if ((varbind->name_length + 1) * sizeof(oid) <= 40) {
394                     for (i = 0; i < (int) varbind->name_length; i++)
395                         new_index->varbind->val.objid[i] =
396                             varbind->name[i];
397                     new_index->varbind->val.objid[varbind->name_length] =
398                         1;
399                     new_index->varbind->val_len =
400                         (varbind->name_length + 1) * sizeof(oid);
401                 } else {
402                     /*
403                      * Otherwise use '.1.1.1.1...' 
404                      */
405                     i = 40 / sizeof(oid);
406                     if (i > 4)
407                         i = 4;
408                     new_index->varbind->val_len = i * (sizeof(oid));
409                     for (i--; i >= 0; i--)
410                         new_index->varbind->val.objid[i] = 1;
411                 }
412             }
413             break;
414         default:
415             snmp_free_var(new_index->varbind);
416             free(new_index);
417             return NULL;        /* Index type not supported */
418         }
419     }
420
421     /*
422      * Try to duplicate the new varbind for return.  
423      */
424
425     if ((rv = snmp_clone_varbind(new_index->varbind)) == NULL) {
426         snmp_free_var(new_index->varbind);
427         free(new_index);
428         return NULL;
429     }
430
431     /*
432      * Right - we've set up the new entry.
433      * All that remains is to link it into the tree.
434      * There are a number of possible cases here,
435      *   so watch carefully.
436      */
437     if (prev_idx_ptr) {
438         new_index->next_idx = prev_idx_ptr->next_idx;
439         new_index->next_oid = prev_idx_ptr->next_oid;
440         prev_idx_ptr->next_idx = new_index;
441     } else {
442         if (res == 0 && idxptr) {
443             new_index->next_idx = idxptr;
444             new_index->next_oid = idxptr->next_oid;
445         } else {
446             new_index->next_idx = NULL;
447             new_index->next_oid = idxptr;
448         }
449
450         if (prev_oid_ptr) {
451             while (prev_oid_ptr) {
452                 prev_oid_ptr->next_oid = new_index;
453                 prev_oid_ptr = prev_oid_ptr->next_idx;
454             }
455         } else
456             snmp_index_head = new_index;
457     }
458     return rv;
459 }
460
461         /*
462          * Release an allocated index,
463          *   to allow it to be used elsewhere
464          */
465 int
466 release_index(netsnmp_variable_list * varbind)
467 {
468     return (unregister_index(varbind, TRUE, NULL));
469 }
470
471         /*
472          * Completely remove an allocated index,
473          *   due to errors in the registration process.
474          */
475 int
476 remove_index(netsnmp_variable_list * varbind, netsnmp_session * ss)
477 {
478     return (unregister_index(varbind, FALSE, ss));
479 }
480
481 void
482 unregister_index_by_session(netsnmp_session * ss)
483 {
484     struct snmp_index *idxptr, *idxptr2;
485     for (idxptr = snmp_index_head; idxptr != NULL;
486          idxptr = idxptr->next_oid)
487         for (idxptr2 = idxptr; idxptr2 != NULL;
488              idxptr2 = idxptr2->next_idx)
489             if (idxptr2->session == ss) {
490                 idxptr2->allocated = 0;
491                 idxptr2->session = NULL;
492             }
493 }
494
495
496 int
497 unregister_index(netsnmp_variable_list * varbind, int remember,
498                  netsnmp_session * ss)
499 {
500     struct snmp_index *idxptr, *idxptr2;
501     struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
502     int             res, res2, i;
503
504 #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
505     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
506                                NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
507         return (agentx_unregister_index(ss, varbind));
508     }
509 #endif
510     /*
511      * Look for the requested OID entry 
512      */
513     prev_oid_ptr = NULL;
514     prev_idx_ptr = NULL;
515     res = 1;
516     res2 = 1;
517     for (idxptr = snmp_index_head; idxptr != NULL;
518          prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
519         if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
520                                     idxptr->varbind->name,
521                                     idxptr->varbind->name_length)) <= 0)
522             break;
523     }
524
525     if (res != 0)
526         return INDEX_ERR_NOT_ALLOCATED;
527     if (varbind->type != idxptr->varbind->type)
528         return INDEX_ERR_WRONG_TYPE;
529
530     for (idxptr2 = idxptr; idxptr2 != NULL;
531          prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
532         i = SNMP_MIN(varbind->val_len, idxptr2->varbind->val_len);
533         res2 =
534             memcmp(varbind->val.string, idxptr2->varbind->val.string, i);
535         if (res2 <= 0)
536             break;
537     }
538     if (res2 != 0 || (res2 == 0 && !idxptr2->allocated)) {
539         return INDEX_ERR_NOT_ALLOCATED;
540     }
541     if (ss != idxptr2->session)
542         return INDEX_ERR_WRONG_SESSION;
543
544     /*
545      *  If this is a "normal" index unregistration,
546      *      mark the index entry as unused, but leave
547      *      it in situ.  This allows differentiation
548      *      between ANY_INDEX and NEW_INDEX
549      */
550     if (remember) {
551         idxptr2->allocated = 0; /* Unused index */
552         idxptr2->session = NULL;
553         return SNMP_ERR_NOERROR;
554     }
555     /*
556      *  If this is a failed attempt to register a
557      *      number of indexes, the successful ones
558      *      must be removed completely.
559      */
560     if (prev_idx_ptr) {
561         prev_idx_ptr->next_idx = idxptr2->next_idx;
562     } else if (prev_oid_ptr) {
563         if (idxptr2->next_idx)  /* Use p_idx_ptr as a temp variable */
564             prev_idx_ptr = idxptr2->next_idx;
565         else
566             prev_idx_ptr = idxptr2->next_oid;
567         while (prev_oid_ptr) {
568             prev_oid_ptr->next_oid = prev_idx_ptr;
569             prev_oid_ptr = prev_oid_ptr->next_idx;
570         }
571     } else {
572         if (idxptr2->next_idx)
573             snmp_index_head = idxptr2->next_idx;
574         else
575             snmp_index_head = idxptr2->next_oid;
576     }
577     snmp_free_var(idxptr2->varbind);
578     free(idxptr2);
579     return SNMP_ERR_NOERROR;
580 }
581
582 int
583 unregister_string_index(oid * name, size_t name_len, char *cp)
584 {
585     netsnmp_variable_list varbind;
586
587     memset(&varbind, 0, sizeof(netsnmp_variable_list));
588     varbind.type = ASN_OCTET_STR;
589     snmp_set_var_objid(&varbind, name, name_len);
590     snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
591     return (unregister_index(&varbind, FALSE, main_session));
592 }
593
594 int
595 unregister_int_index(oid * name, size_t name_len, int val)
596 {
597     netsnmp_variable_list varbind;
598
599     memset(&varbind, 0, sizeof(netsnmp_variable_list));
600     varbind.type = ASN_INTEGER;
601     snmp_set_var_objid(&varbind, name, name_len);
602     varbind.val.string = varbind.buf;
603     varbind.val_len = sizeof(long);
604     *varbind.val.integer = val;
605     return (unregister_index(&varbind, FALSE, main_session));
606 }
607
608 int
609 unregister_oid_index(oid * name, size_t name_len,
610                      oid * value, size_t value_len)
611 {
612     netsnmp_variable_list varbind;
613
614     memset(&varbind, 0, sizeof(netsnmp_variable_list));
615     varbind.type = ASN_OBJECT_ID;
616     snmp_set_var_objid(&varbind, name, name_len);
617     snmp_set_var_value(&varbind, (u_char *) value,
618                        value_len * sizeof(oid));
619     return (unregister_index(&varbind, FALSE, main_session));
620 }
621 #endif /* not defined BUILD_ILMI */
622
623 #ifdef BRCM_SNMP_DEBUG
624 void
625 dump_idx_registry(void)
626 {
627     struct snmp_index *idxptr, *idxptr2;
628     u_char         *sbuf = NULL, *ebuf = NULL;
629     size_t          sbuf_len = 0, sout_len = 0, ebuf_len = 0, eout_len = 0;
630
631     if (snmp_index_head != NULL) {
632         printf("\nIndex Allocations:\n");
633     }
634
635     for (idxptr = snmp_index_head; idxptr != NULL;
636          idxptr = idxptr->next_oid) {
637         sout_len = 0;
638         if (sprint_realloc_objid(&sbuf, &sbuf_len, &sout_len, 1,
639                                  idxptr->varbind->name,
640                                  idxptr->varbind->name_length)) {
641             printf("%s indexes:\n", sbuf);
642         } else {
643             printf("%s [TRUNCATED] indexes:\n", sbuf);
644         }
645
646         for (idxptr2 = idxptr; idxptr2 != NULL;
647              idxptr2 = idxptr2->next_idx) {
648             switch (idxptr2->varbind->type) {
649             case ASN_INTEGER:
650                 printf("    %ld for session %8p, allocated %d\n",
651                        *idxptr2->varbind->val.integer, idxptr2->session,
652                        idxptr2->allocated);
653                 break;
654             case ASN_OCTET_STR:
655                 printf("    \"%s\" for session %8p, allocated %d\n",
656                        idxptr2->varbind->val.string, idxptr2->session,
657                        idxptr2->allocated);
658                 break;
659             case ASN_OBJECT_ID:
660                 eout_len = 0;
661                 if (sprint_realloc_objid(&ebuf, &ebuf_len, &eout_len, 1,
662                                          idxptr2->varbind->val.objid,
663                                          idxptr2->varbind->val_len /
664                                          sizeof(oid))) {
665                     printf("    %s for session %8p, allocated %d\n", ebuf,
666                            idxptr2->session, idxptr2->allocated);
667                 } else {
668                     printf
669                         ("    %s [TRUNCATED] for sess %8p, allocated %d\n",
670                          ebuf, idxptr2->session, idxptr2->allocated);
671                 }
672                 break;
673             default:
674                 printf("unsupported type (%d/0x%02x)\n",
675                        idxptr2->varbind->type, idxptr2->varbind->type);
676             }
677         }
678     }
679
680     if (sbuf != NULL) {
681         free(sbuf);
682     }
683     if (ebuf != NULL) {
684         free(ebuf);
685     }
686 }
687
688 unsigned long
689 count_indexes(oid * name, size_t namelen, int include_unallocated)
690 {
691     struct snmp_index *i = NULL, *j = NULL;
692     unsigned long   n = 0;
693
694     for (i = snmp_index_head; i != NULL; i = i->next_oid) {
695         if (netsnmp_oid_equals(name, namelen,
696                              i->varbind->name,
697                              i->varbind->name_length) == 0) {
698             for (j = i; j != NULL; j = j->next_idx) {
699                 if (j->allocated || include_unallocated) {
700                     n++;
701                 }
702             }
703         }
704     }
705     return n;
706 }
707 #endif /* BRCM_SNMP_DEBUG */
708
709 #ifndef BUILD_ILMI
710 #ifdef TESTING
711 netsnmp_variable_list varbind;
712 netsnmp_session main_sess, *main_session = &main_sess;
713
714 void
715 test_string_register(int n, char *cp)
716 {
717     varbind->name[4] = n;
718     if (register_string_index(varbind->name, varbind.name_length, cp) ==
719         NULL)
720         printf("allocating %s failed\n", cp);
721 }
722
723 void
724 test_int_register(int n, int val)
725 {
726     varbind->name[4] = n;
727     if (register_int_index(varbind->name, varbind.name_length, val) == -1)
728         printf("allocating %d/%d failed\n", n, val);
729 }
730
731 void
732 test_oid_register(int n, int subid)
733 {
734     netsnmp_variable_list *res;
735
736     varbind->name[4] = n;
737     if (subid != -1) {
738         varbind->val.objid[5] = subid;
739         res = register_oid_index(varbind->name, varbind.name_length,
740                                  varbind->val.objid,
741                                  varbind->val_len / sizeof(oid));
742     } else
743         res =
744             register_oid_index(varbind->name, varbind.name_length, NULL,
745                                0);
746
747     if (res == NULL)
748         printf("allocating %d/%d failed\n", n, subid);
749 }
750
751 void
752 main(int argc, char argv[])
753 {
754     oid             name[] = { 1, 2, 3, 4, 0 };
755     int             i;
756
757     memset(&varbind, 0, sizeof(netsnmp_variable_list));
758     snmp_set_var_objid(&varbind, name, 5);
759     varbind->type = ASN_OCTET_STR;
760     /*
761      * Test index structure linking:
762      *      a) sorted by OID
763      */
764     test_string_register(20, "empty OID");
765     test_string_register(10, "first OID");
766     test_string_register(40, "last OID");
767     test_string_register(30, "middle OID");
768
769     /*
770      *      b) sorted by index value
771      */
772     test_string_register(25, "eee: empty IDX");
773     test_string_register(25, "aaa: first IDX");
774     test_string_register(25, "zzz: last IDX");
775     test_string_register(25, "mmm: middle IDX");
776     printf("This next one should fail....\n");
777     test_string_register(25, "eee: empty IDX"); /* duplicate */
778     printf("done\n");
779
780     /*
781      *      c) test initial index linking
782      */
783     test_string_register(5, "eee: empty initial IDX");
784     test_string_register(5, "aaa: replace initial IDX");
785
786     /*
787      *      Did it all work?
788      */
789     dump_idx_registry();
790     unregister_index_by_session(main_session);
791     /*
792      *  Now test index allocation
793      *      a) integer values
794      */
795     test_int_register(110, -1); /* empty */
796     test_int_register(110, -1); /* append */
797     test_int_register(110, 10); /* append exact */
798     printf("This next one should fail....\n");
799     test_int_register(110, 10); /* exact duplicate */
800     printf("done\n");
801     test_int_register(110, -1); /* append */
802     test_int_register(110, 5);  /* insert exact */
803
804     /*
805      *      b) string values
806      */
807     test_string_register(120, NULL);    /* empty */
808     test_string_register(120, NULL);    /* append */
809     test_string_register(120, "aaaz");
810     test_string_register(120, NULL);    /* minor rollover */
811     test_string_register(120, "zzzz");
812     test_string_register(120, NULL);    /* major rollover */
813
814     /*
815      *      c) OID values
816      */
817
818     test_oid_register(130, -1); /* empty */
819     test_oid_register(130, -1); /* append */
820
821     varbind->val_len = varbind.name_length * sizeof(oid);
822     memcpy(varbind->buf, varbind.name, varbind.val_len);
823     varbind->val.objid = (oid *) varbind.buf;
824     varbind->val_len += sizeof(oid);
825
826     test_oid_register(130, 255);        /* append exact */
827     test_oid_register(130, -1); /* minor rollover */
828     test_oid_register(130, 100);        /* insert exact */
829     printf("This next one should fail....\n");
830     test_oid_register(130, 100);        /* exact duplicate */
831     printf("done\n");
832
833     varbind->val.objid = (oid *) varbind.buf;
834     for (i = 0; i < 6; i++)
835         varbind->val.objid[i] = 255;
836     varbind->val.objid[0] = 1;
837     test_oid_register(130, 255);        /* set up rollover  */
838     test_oid_register(130, -1); /* medium rollover */
839
840     for (i = 0; i < 6; i++)
841         varbind->val.objid[i] = 255;
842     varbind->val.objid[0] = 2;
843     test_oid_register(130, 255);        /* set up rollover  */
844     test_oid_register(130, -1); /* major rollover */
845
846     /*
847      *      Did it all work?
848      */
849     dump_idx_registry();
850
851     /*
852      *      Test the various "invalid" requests
853      *      (unsupported types, mis-matched types, etc)
854      */
855     printf("The rest of these should fail....\n");
856     test_oid_register(110, -1);
857     test_oid_register(110, 100);
858     test_oid_register(120, -1);
859     test_oid_register(120, 100);
860     test_string_register(110, NULL);
861     test_string_register(110, "aaaa");
862     test_string_register(130, NULL);
863     test_string_register(130, "aaaa");
864     test_int_register(120, -1);
865     test_int_register(120, 1);
866     test_int_register(130, -1);
867     test_int_register(130, 1);
868     printf("done - this dump should be the same as before\n");
869     dump_idx_registry();
870 }
871 #endif
872 #endif /* ifndef BUILD_ILMI */