# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / disman / mteObjectsTable.c
1 /*
2  * This file was generated by mib2c and is intended for use as
3  * a mib module for the ucd-snmp snmpd agent. 
4  */
5
6
7 /*
8  * This should always be included first before anything else 
9  */
10 #include <net-snmp/net-snmp-config.h>
11 #if HAVE_STDLIB_H
12 #include <stdlib.h>
13 #endif
14 #if HAVE_STRING_H
15 #include <string.h>
16 #else
17 #include <strings.h>
18 #endif
19
20
21 /*
22  * minimal include directives 
23  */
24 #include <net-snmp/net-snmp-includes.h>
25 #include <net-snmp/agent/net-snmp-agent-includes.h>
26
27 #include "header_complex.h"
28 #include "mteTriggerTable.h"
29 #include "mteObjectsTable.h"
30
31
32 /*
33  * mteObjectsTable_variables_oid:
34  *   this is the top level oid that we want to register under.  This
35  *   is essentially a prefix, with the suffix appearing in the
36  *   variable below.
37  */
38
39
40 oid             mteObjectsTable_variables_oid[] =
41     { 1, 3, 6, 1, 2, 1, 88, 1, 3, 1 };
42
43
44 /*
45  * variable2 mteObjectsTable_variables:
46  *   this variable defines function callbacks and type return information 
47  *   for the mteObjectsTable mib section 
48  */
49
50
51 struct variable2 mteObjectsTable_variables[] = {
52     /*
53      * magic number        , variable type , ro/rw , callback fn  , L, oidsuffix 
54      */
55 #define   MTEOBJECTSID          5
56     {MTEOBJECTSID, ASN_OBJECT_ID, RWRITE, var_mteObjectsTable, 2, {1, 3}},
57 #define   MTEOBJECTSIDWILDCARD  6
58     {MTEOBJECTSIDWILDCARD, ASN_INTEGER, RWRITE, var_mteObjectsTable, 2,
59      {1, 4}},
60 #define   MTEOBJECTSENTRYSTATUS  7
61     {MTEOBJECTSENTRYSTATUS, ASN_INTEGER, RWRITE, var_mteObjectsTable, 2,
62      {1, 5}},
63
64 };
65 /*
66  * (L = length of the oidsuffix) 
67  */
68
69
70 /*
71  * global storage of our data, saved in and configured by header_complex() 
72  */
73 static struct header_complex_index *mteObjectsTableStorage = NULL;
74
75
76
77
78 /*
79  * init_mteObjectsTable():
80  *   Initialization routine.  This is called when the agent starts up.
81  *   At a minimum, registration of your variables should take place here.
82  */
83 void
84 init_mteObjectsTable(void)
85 {
86     DEBUGMSGTL(("mteObjectsTable", "initializing...  "));
87
88
89     /*
90      * register ourselves with the agent to handle our mib tree 
91      */
92     REGISTER_MIB("mteObjectsTable", mteObjectsTable_variables, variable2,
93                  mteObjectsTable_variables_oid);
94
95
96     /*
97      * register our config handler(s) to deal with registrations 
98      */
99     snmpd_register_config_handler("mteObjectsTable", parse_mteObjectsTable,
100                                   NULL, NULL);
101
102
103     /*
104      * we need to be called back later to store our data 
105      */
106     snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
107                            store_mteObjectsTable, NULL);
108
109
110     /*
111      * place any other initialization junk you need here 
112      */
113
114
115     DEBUGMSGTL(("mteObjectsTable", "done.\n"));
116 }
117
118
119 /*
120  * mteObjectsTable_add(): adds a structure node to our data set 
121  */
122 int
123 mteObjectsTable_add(struct mteObjectsTable_data *thedata)
124 {
125     netsnmp_variable_list *vars = NULL;
126
127
128     DEBUGMSGTL(("mteObjectsTable", "adding data...  "));
129     /*
130      * add the index variables to the varbind list, which is 
131      * used by header_complex to index the data 
132      */
133
134
135     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->mteOwner, thedata->mteOwnerLen); /* mteOwner */
136     snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->mteObjectsName, thedata->mteObjectsNameLen);     /* mteObjectsName */
137     snmp_varlist_add_variable(&vars, NULL, 0, ASN_UNSIGNED, (char *) &thedata->mteObjectsIndex, sizeof(thedata->mteObjectsIndex));      /* mteObjectsIndex */
138
139
140
141     header_complex_add_data(&mteObjectsTableStorage, vars, thedata);
142     DEBUGMSGTL(("mteObjectsTable", "registered an entry\n"));
143
144
145     DEBUGMSGTL(("mteObjectsTable", "done.\n"));
146     return SNMPERR_SUCCESS;
147 }
148
149
150 /*
151  * parse_mteObjectsTable():
152  *   parses .conf file entries needed to configure the mib.
153  */
154 void
155 parse_mteObjectsTable(const char *token, char *line)
156 {
157     size_t          tmpint;
158     struct mteObjectsTable_data *StorageTmp =
159         SNMP_MALLOC_STRUCT(mteObjectsTable_data);
160
161     DEBUGMSGTL(("mteObjectsTable", "parsing config...  "));
162
163
164     if (StorageTmp == NULL) {
165         config_perror("malloc failure");
166         return;
167     }
168
169
170     line =
171         read_config_read_data(ASN_OCTET_STR, line, &StorageTmp->mteOwner,
172                               &StorageTmp->mteOwnerLen);
173     if (StorageTmp->mteOwner == NULL) {
174         config_perror("invalid specification for mteOwner");
175         return;
176     }
177
178     line =
179         read_config_read_data(ASN_OCTET_STR, line,
180                               &StorageTmp->mteObjectsName,
181                               &StorageTmp->mteObjectsNameLen);
182     if (StorageTmp->mteObjectsName == NULL) {
183         config_perror("invalid specification for mteObjectsName");
184         return;
185     }
186
187     line =
188         read_config_read_data(ASN_UNSIGNED, line,
189                               &StorageTmp->mteObjectsIndex, &tmpint);
190
191     line =
192         read_config_read_data(ASN_OBJECT_ID, line,
193                               &StorageTmp->mteObjectsID,
194                               &StorageTmp->mteObjectsIDLen);
195     if (StorageTmp->mteObjectsID == NULL) {
196         config_perror("invalid specification for mteObjectsID");
197         return;
198     }
199
200     line =
201         read_config_read_data(ASN_INTEGER, line,
202                               &StorageTmp->mteObjectsIDWildcard, &tmpint);
203
204     line =
205         read_config_read_data(ASN_INTEGER, line,
206                               &StorageTmp->mteObjectsEntryStatus, &tmpint);
207
208
209
210
211     mteObjectsTable_add(StorageTmp);
212
213
214     DEBUGMSGTL(("mteObjectsTable", "done.\n"));
215 }
216
217
218
219
220 /*
221  * store_mteObjectsTable():
222  *   stores .conf file entries needed to configure the mib.
223  */
224 int
225 store_mteObjectsTable(int majorID, int minorID, void *serverarg,
226                       void *clientarg)
227 {
228     char            line[SNMP_MAXBUF];
229     char           *cptr;
230     size_t          tmpint;
231     struct mteObjectsTable_data *StorageTmp;
232     struct header_complex_index *hcindex;
233
234
235     DEBUGMSGTL(("mteObjectsTable", "storing data...  "));
236
237
238     for (hcindex = mteObjectsTableStorage; hcindex != NULL;
239          hcindex = hcindex->next) {
240         StorageTmp = (struct mteObjectsTable_data *) hcindex->data;
241
242         if (StorageTmp->storagetype != ST_READONLY) {
243             memset(line, 0, sizeof(line));
244             strcat(line, "mteObjectsTable ");
245             cptr = line + strlen(line);
246
247
248             cptr =
249                 read_config_store_data(ASN_OCTET_STR, cptr,
250                                        &StorageTmp->mteOwner,
251                                        &StorageTmp->mteOwnerLen);
252             cptr =
253                 read_config_store_data(ASN_OCTET_STR, cptr,
254                                        &StorageTmp->mteObjectsName,
255                                        &StorageTmp->mteObjectsNameLen);
256             cptr =
257                 read_config_store_data(ASN_UNSIGNED, cptr,
258                                        &StorageTmp->mteObjectsIndex,
259                                        &tmpint);
260             cptr =
261                 read_config_store_data(ASN_OBJECT_ID, cptr,
262                                        &StorageTmp->mteObjectsID,
263                                        &StorageTmp->mteObjectsIDLen);
264             cptr =
265                 read_config_store_data(ASN_INTEGER, cptr,
266                                        &StorageTmp->mteObjectsIDWildcard,
267                                        &tmpint);
268             cptr =
269                 read_config_store_data(ASN_INTEGER, cptr,
270                                        &StorageTmp->mteObjectsEntryStatus,
271                                        &tmpint);
272
273
274
275             snmpd_store_config(line);
276         }
277     }
278     DEBUGMSGTL(("mteObjectsTable", "done.\n"));
279     return SNMPERR_SUCCESS;
280 }
281
282
283
284
285 /*
286  * var_mteObjectsTable():
287  *   Handle this table separately from the scalar value case.
288  *   The workings of this are basically the same as for var_mteObjectsTable above.
289  */
290 unsigned char  *
291 var_mteObjectsTable(struct variable *vp,
292                     oid * name,
293                     size_t * length,
294                     int exact,
295                     size_t * var_len, WriteMethod ** write_method)
296 {
297
298
299     struct mteObjectsTable_data *StorageTmp = NULL;
300
301
302     DEBUGMSGTL(("mteObjectsTable",
303                 "var_mteObjectsTable: Entering...  \n"));
304     /*
305      * this assumes you have registered all your data properly
306      */
307     if ((StorageTmp =
308          header_complex(mteObjectsTableStorage, vp, name, length, exact,
309                         var_len, write_method)) == NULL) {
310         if (vp->magic == MTEOBJECTSENTRYSTATUS)
311             *write_method = write_mteObjectsEntryStatus;
312         return NULL;
313     }
314
315     /*
316      * this is where we do the value assignments for the mib results.
317      */
318     switch (vp->magic) {
319
320
321     case MTEOBJECTSID:
322         *write_method = write_mteObjectsID;
323         *var_len = (StorageTmp->mteObjectsIDLen) * sizeof(oid);
324         return (u_char *) StorageTmp->mteObjectsID;
325
326     case MTEOBJECTSIDWILDCARD:
327         *write_method = write_mteObjectsIDWildcard;
328         *var_len = sizeof(StorageTmp->mteObjectsIDWildcard);
329         return (u_char *) & StorageTmp->mteObjectsIDWildcard;
330
331     case MTEOBJECTSENTRYSTATUS:
332         *write_method = write_mteObjectsEntryStatus;
333         *var_len = sizeof(StorageTmp->mteObjectsEntryStatus);
334         return (u_char *) & StorageTmp->mteObjectsEntryStatus;
335
336
337     default:
338         ERROR_MSG("");
339     }
340     return NULL;
341 }
342
343
344
345
346 int
347 write_mteObjectsID(int action,
348                    u_char * var_val,
349                    u_char var_val_type,
350                    size_t var_val_len,
351                    u_char * statP, oid * name, size_t name_len)
352 {
353     static oid     *tmpvar;
354     struct mteObjectsTable_data *StorageTmp = NULL;
355     static size_t   tmplen;
356     size_t          newlen =
357         name_len - (sizeof(mteObjectsTable_variables_oid) / sizeof(oid) +
358                     3 - 1);
359
360
361     DEBUGMSGTL(("mteObjectsTable",
362                 "write_mteObjectsID entering action=%d...  \n", action));
363     if ((StorageTmp =
364          header_complex(mteObjectsTableStorage, NULL,
365                         &name[sizeof(mteObjectsTable_variables_oid) /
366                               sizeof(oid) + 3 - 1], &newlen, 1, NULL,
367                         NULL)) == NULL)
368         return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */
369
370     if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
371         return SNMP_ERR_NOTWRITABLE;
372     }
373
374     switch (action) {
375     case RESERVE1:
376         if (var_val_type != ASN_OBJECT_ID) {
377             snmp_log(LOG_ERR, "write to mteObjectsID not ASN_OBJECT_ID\n");
378             return SNMP_ERR_WRONGTYPE;
379         }
380         break;
381
382
383     case RESERVE2:
384         /*
385          * memory reseveration, final preparation... 
386          */
387         break;
388
389
390     case FREE:
391         /*
392          * Release any resources that have been allocated 
393          */
394         break;
395
396
397     case ACTION:
398         /*
399          * The variable has been stored in objid for
400          * you to use, and you have just been asked to do something with
401          * it.  Note that anything done here must be reversable in the UNDO case 
402          */
403         tmpvar = StorageTmp->mteObjectsID;
404         tmplen = StorageTmp->mteObjectsIDLen;
405         memdup((u_char **) & StorageTmp->mteObjectsID, var_val,
406                var_val_len);
407         StorageTmp->mteObjectsIDLen = var_val_len / sizeof(oid);
408         break;
409
410
411     case UNDO:
412         /*
413          * Back out any changes made in the ACTION case 
414          */
415         SNMP_FREE(StorageTmp->mteObjectsID);
416         StorageTmp->mteObjectsID = tmpvar;
417         StorageTmp->mteObjectsIDLen = tmplen;
418         break;
419
420
421     case COMMIT:
422         /*
423          * Things are working well, so it's now safe to make the change
424          * permanently.  Make sure that anything done here can't fail! 
425          */
426         SNMP_FREE(tmpvar);
427         break;
428     }
429     return SNMP_ERR_NOERROR;
430 }
431
432
433
434 int
435 write_mteObjectsIDWildcard(int action,
436                            u_char * var_val,
437                            u_char var_val_type,
438                            size_t var_val_len,
439                            u_char * statP, oid * name, size_t name_len)
440 {
441     static int      tmpvar;
442     struct mteObjectsTable_data *StorageTmp = NULL;
443     size_t          newlen =
444         name_len - (sizeof(mteObjectsTable_variables_oid) / sizeof(oid) +
445                     3 - 1);
446
447
448     DEBUGMSGTL(("mteObjectsTable",
449                 "write_mteObjectsIDWildcard entering action=%d...  \n",
450                 action));
451     if ((StorageTmp =
452          header_complex(mteObjectsTableStorage, NULL,
453                         &name[sizeof(mteObjectsTable_variables_oid) /
454                               sizeof(oid) + 3 - 1], &newlen, 1, NULL,
455                         NULL)) == NULL)
456         return SNMP_ERR_NOSUCHNAME;     /* remove if you support creation here */
457
458     if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
459         return SNMP_ERR_NOTWRITABLE;
460     }
461
462     switch (action) {
463     case RESERVE1:
464         if (var_val_type != ASN_INTEGER) {
465             snmp_log(LOG_ERR,
466                      "write to mteObjectsIDWildcard not ASN_INTEGER\n");
467             return SNMP_ERR_WRONGTYPE;
468         }
469         break;
470
471
472     case RESERVE2:
473         /*
474          * memory reseveration, final preparation... 
475          */
476         break;
477
478
479     case FREE:
480         /*
481          * Release any resources that have been allocated 
482          */
483         break;
484
485
486     case ACTION:
487         /*
488          * The variable has been stored in long_ret for
489          * you to use, and you have just been asked to do something with
490          * it.  Note that anything done here must be reversable in the UNDO case 
491          */
492         tmpvar = StorageTmp->mteObjectsIDWildcard;
493         StorageTmp->mteObjectsIDWildcard = *((long *) var_val);
494         break;
495
496
497     case UNDO:
498         /*
499          * Back out any changes made in the ACTION case 
500          */
501         StorageTmp->mteObjectsIDWildcard = tmpvar;
502         break;
503
504
505     case COMMIT:
506         /*
507          * Things are working well, so it's now safe to make the change
508          * permanently.  Make sure that anything done here can't fail! 
509          */
510
511         break;
512     }
513     return SNMP_ERR_NOERROR;
514 }
515
516
517
518
519
520
521 int
522 write_mteObjectsEntryStatus(int action,
523                             u_char * var_val,
524                             u_char var_val_type,
525                             size_t var_val_len,
526                             u_char * statP, oid * name, size_t name_len)
527 {
528     struct mteObjectsTable_data *StorageTmp = NULL;
529     static struct mteObjectsTable_data *StorageNew, *StorageDel;
530     size_t          newlen =
531         name_len - (sizeof(mteObjectsTable_variables_oid) / sizeof(oid) +
532                     3 - 1);
533     static int      old_value;
534     int             set_value;
535     static netsnmp_variable_list *vars, *vp;
536     struct header_complex_index *hciptr;
537
538
539     StorageTmp =
540         header_complex(mteObjectsTableStorage, NULL,
541                        &name[sizeof(mteObjectsTable_variables_oid) /
542                              sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);
543
544     if (var_val_type != ASN_INTEGER || var_val == NULL) {
545         snmp_log(LOG_ERR,
546                  "write to mteObjectsEntryStatus not ASN_INTEGER\n");
547         return SNMP_ERR_WRONGTYPE;
548     }
549
550     if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
551         return SNMP_ERR_NOTWRITABLE;
552     }
553
554     set_value = *((long *) var_val);
555
556
557     /*
558      * check legal range, and notReady is reserved for us, not a user 
559      */
560     if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
561         return SNMP_ERR_INCONSISTENTVALUE;
562
563
564     switch (action) {
565     case RESERVE1:
566         /*
567          * stage one: test validity 
568          */
569         if (StorageTmp == NULL) {
570             /*
571              * create the row now? 
572              */
573
574
575             /*
576              * ditch illegal values now 
577              */
578             if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE)
579                 return SNMP_ERR_INCONSISTENTVALUE;
580
581
582             /*
583              * destroying a non-existent row is actually legal 
584              */
585             if (set_value == RS_DESTROY) {
586                 return SNMP_ERR_NOERROR;
587             }
588
589
590             /*
591              * illegal creation values 
592              */
593             if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
594                 return SNMP_ERR_INCONSISTENTVALUE;
595             }
596         } else {
597             /*
598              * row exists.  Check for a valid state change 
599              */
600             if (set_value == RS_CREATEANDGO
601                 || set_value == RS_CREATEANDWAIT) {
602                 /*
603                  * can't create a row that exists 
604                  */
605                 return SNMP_ERR_INCONSISTENTVALUE;
606             }
607             /*
608              * XXX: interaction with row storage type needed 
609              */
610         }
611         break;
612
613
614
615
616     case RESERVE2:
617         /*
618          * memory reseveration, final preparation... 
619          */
620         if (StorageTmp == NULL) {
621             /*
622              * creation 
623              */
624             vars = NULL;
625
626
627             snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0);  /* mteOwner */
628             snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0);  /* mteObjectsName */
629             snmp_varlist_add_variable(&vars, NULL, 0, ASN_UNSIGNED, NULL, 0);   /* mteObjectsIndex */
630
631             if (header_complex_parse_oid
632                 (&
633                  (name
634                   [sizeof(mteObjectsTable_variables_oid) / sizeof(oid) +
635                    2]), newlen, vars) != SNMPERR_SUCCESS) {
636                 /*
637                  * XXX: free, zero vars 
638                  */
639                 return SNMP_ERR_INCONSISTENTNAME;
640             }
641             vp = vars;
642
643
644             StorageNew = SNMP_MALLOC_STRUCT(mteObjectsTable_data);
645             StorageNew->mteOwner = netsnmp_strdup_and_null(vp->val.string,
646                                                            vp->val_len);
647             StorageNew->mteOwnerLen = vp->val_len;
648             vp = vp->next_variable;
649             StorageNew->mteObjectsName  =
650                 netsnmp_strdup_and_null(vp->val.string,
651                                         vp->val_len);
652             StorageNew->mteObjectsNameLen = vp->val_len;
653             vp = vp->next_variable;
654             StorageNew->mteObjectsIndex = *(vp->val.integer);
655
656             /*
657              * XXX: fill in default row values here into StorageNew 
658              */
659             StorageNew->mteObjectsID = calloc(1, sizeof(oid) * sizeof(2));      /* 0.0 */
660             StorageNew->mteObjectsIDLen = 2;
661             StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_FALSE;
662
663             StorageNew->mteObjectsEntryStatus = set_value;
664             /*
665              * XXX: free, zero vars, no longer needed? 
666              */
667         }
668
669
670         break;
671
672
673
674
675     case FREE:
676         /*
677          * XXX: free, zero vars 
678          */
679         /*
680          * Release any resources that have been allocated 
681          */
682         break;
683
684
685
686
687     case ACTION:
688         /*
689          * The variable has been stored in set_value for you to
690          * use, and you have just been asked to do something with
691          * it.  Note that anything done here must be reversable in
692          * the UNDO case 
693          */
694
695
696         if (StorageTmp == NULL) {
697             /*
698              * row creation, so add it 
699              */
700             if (StorageNew != NULL)
701                 mteObjectsTable_add(StorageNew);
702             /*
703              * XXX: ack, and if it is NULL? 
704              */
705         } else if (set_value != RS_DESTROY) {
706             /*
707              * set the flag? 
708              */
709             old_value = StorageTmp->mteObjectsEntryStatus;
710             StorageTmp->mteObjectsEntryStatus = *((long *) var_val);
711         } else {
712             /*
713              * destroy...  extract it for now 
714              */
715             hciptr =
716                 header_complex_find_entry(mteObjectsTableStorage,
717                                           StorageTmp);
718             StorageDel =
719                 header_complex_extract_entry(&mteObjectsTableStorage,
720                                              hciptr);
721         }
722         break;
723
724
725
726
727     case UNDO:
728         /*
729          * Back out any changes made in the ACTION case 
730          */
731         if (StorageTmp == NULL) {
732             /*
733              * row creation, so remove it again 
734              */
735             hciptr =
736                 header_complex_find_entry(mteObjectsTableStorage,
737                                           StorageTmp);
738             StorageDel =
739                 header_complex_extract_entry(&mteObjectsTableStorage,
740                                              hciptr);
741             /*
742              * XXX: free it 
743              */
744         } else if (StorageDel != NULL) {
745             /*
746              * row deletion, so add it again 
747              */
748             mteObjectsTable_add(StorageDel);
749         } else {
750             StorageTmp->mteObjectsEntryStatus = old_value;
751         }
752         break;
753
754
755
756
757     case COMMIT:
758         /*
759          * Things are working well, so it's now safe to make the change
760          * permanently.  Make sure that anything done here can't fail! 
761          */
762         if (StorageDel != NULL) {
763             StorageDel = 0;
764             /*
765              * XXX: free it, its dead 
766              */
767         } else {
768             if (StorageTmp
769                 && StorageTmp->mteObjectsEntryStatus == RS_CREATEANDGO) {
770                 StorageTmp->mteObjectsEntryStatus = RS_ACTIVE;
771             } else if (StorageTmp &&
772                        StorageTmp->mteObjectsEntryStatus ==
773                        RS_CREATEANDWAIT) {
774                 StorageTmp->mteObjectsEntryStatus = RS_NOTINSERVICE;
775             }
776         }
777         break;
778     }
779     return SNMP_ERR_NOERROR;
780 }
781
782 void
783 mte_add_objects(netsnmp_variable_list * vars,
784                 struct mteTriggerTable_data *item, const char *owner,
785                 const char *name, oid * suffix, size_t suffix_len)
786 {
787     struct header_complex_index *hcptr = mteObjectsTableStorage;
788
789     DEBUGMSGTL(("mteObjectsTable",
790                 "Searching for objects to add for owner=%s / name=%s\n",
791                 owner, name));
792
793     if (vars == NULL || item == NULL || owner == NULL || name == NULL ||
794         hcptr == NULL)
795         return;
796
797     /*
798      * get to end of variable chain 
799      */
800     while (vars->next_variable != NULL)
801         vars = vars->next_variable;
802
803
804     /*
805      * get to start of objects list 
806      */
807     while (hcptr &&
808            (strcmp(((struct mteObjectsTable_data *) hcptr->data)->mteOwner,
809                    owner) != 0 ||
810             strcmp(((struct mteObjectsTable_data *) hcptr->data)->
811                    mteObjectsName, name) != 0))
812         hcptr = hcptr->next;
813
814     /*
815      * add all objects 
816      */
817     while (hcptr &&
818            strcmp(((struct mteObjectsTable_data *) hcptr->data)->mteOwner,
819                   owner) == 0 &&
820            strcmp(((struct mteObjectsTable_data *) hcptr->data)->
821                   mteObjectsName, name) == 0) {
822         /*
823          * loop through objects 
824          */
825         netsnmp_pdu    *pdu = NULL, *response = NULL;
826         struct mteObjectsTable_data *node =
827             (struct mteObjectsTable_data *) hcptr->data;
828         oid             theoid[MAX_OID_LEN];
829         size_t          theoid_len;
830
831         /*
832          * copy in the suffix 
833          */
834         memcpy(theoid, node->mteObjectsID,
835                node->mteObjectsIDLen * sizeof(oid));
836         theoid_len = node->mteObjectsIDLen;
837         if (node->mteObjectsIDWildcard == MTEOBJECTSIDWILDCARD_TRUE &&
838             suffix && suffix_len > 0) {
839             theoid_len += suffix_len;
840             if (theoid_len > MAX_OID_LEN) {
841                 break;          /* XXX: properly send trap or something? */
842             }
843
844             memcpy(&theoid[node->mteObjectsIDLen], suffix,
845                    suffix_len * sizeof(oid));
846         }
847
848         /*
849          * retrieve the value 
850          */
851         pdu = snmp_pdu_create(SNMP_MSG_GET);
852         snmp_add_null_var(pdu, theoid, theoid_len);
853         response = mte_get_response(item, pdu);
854
855         if (response) {
856             if (vars) {
857                 vars->next_variable = response->variables;
858                 vars = vars->next_variable;
859                 DEBUGMSGTL(("mteObjectsTable", "Adding:  "));
860                 DEBUGMSGOID(("mteObjectsTable", response->variables->name,
861                              response->variables->name_length));
862                 DEBUGMSG(("mteObjectsTable", "\n"));
863             } else {
864                 vars = response->variables;
865             }
866             /*
867              * erase response notion of the values we stole from it 
868              */
869             response->variables = NULL;
870             snmp_free_pdu(response);
871         }
872
873         /*
874          * move along 
875          */
876         hcptr = hcptr->next;
877     }
878     DEBUGMSGTL(("mteObjectsTable", "Done adding objects\n"));
879 }
880
881 int
882 mte_add_object_to_table(const char *owner, const char *objname,
883                         oid * oidname, size_t oidname_len, int iswild)
884 {
885     struct header_complex_index *hcptr = mteObjectsTableStorage, *lastnode;
886     static struct mteObjectsTable_data *StorageNew;
887
888     /*
889      * malloc initial struct 
890      */
891     StorageNew = SNMP_MALLOC_STRUCT(mteObjectsTable_data);
892     StorageNew->mteOwner = netsnmp_strdup_and_null(owner, strlen(owner));
893     StorageNew->mteOwnerLen = strlen(owner);
894     StorageNew->mteObjectsName = netsnmp_strdup_and_null(objname,
895                                                          strlen(objname));
896     StorageNew->mteObjectsNameLen = strlen(objname);
897
898     /*
899      * find the next number 
900      */
901     /*
902      * get to start of objects list 
903      */
904     while (hcptr &&
905            (strcmp(((struct mteObjectsTable_data *) hcptr->data)->mteOwner,
906                    owner) != 0 ||
907             strcmp(((struct mteObjectsTable_data *) hcptr->data)->
908                    mteObjectsName, objname) != 0))
909         hcptr = hcptr->next;
910
911     if (hcptr) {
912         /*
913          * an object existed.  Find the first one past and increment
914          * the previous number 
915          */
916         lastnode = hcptr;
917         while (hcptr &&
918                strcmp(((struct mteObjectsTable_data *) hcptr->data)->
919                       mteOwner, owner) == 0
920                && strcmp(((struct mteObjectsTable_data *) hcptr->data)->
921                          mteObjectsName, objname) == 0) {
922             lastnode = hcptr;
923             hcptr = hcptr->next;
924         }
925         StorageNew->mteObjectsIndex =
926             ((struct mteObjectsTable_data *) lastnode->data)->
927             mteObjectsIndex + 1;
928     } else {
929         StorageNew->mteObjectsIndex = 1;
930     }
931
932     /*
933      * XXX: fill in default row values here into StorageNew 
934      */
935     StorageNew->mteObjectsID = snmp_duplicate_objid(oidname, oidname_len);
936     StorageNew->mteObjectsIDLen = oidname_len;
937
938     if (iswild)
939         StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_TRUE;
940     else
941         StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_FALSE;
942
943     StorageNew->mteObjectsEntryStatus = RS_ACTIVE;
944     StorageNew->storagetype = ST_READONLY;
945     return mteObjectsTable_add(StorageNew);
946 }