net-snmp  5.4.1
snmp_enum.c
00001 #include <net-snmp/net-snmp-config.h>
00002 
00003 #ifdef HAVE_STDLIB_H
00004 #include <stdlib.h>
00005 #endif
00006 #include <stdio.h>
00007 #if HAVE_STRING_H
00008 #include <string.h>
00009 #else
00010 #include <strings.h>
00011 #endif
00012 
00013 #if HAVE_DMALLOC_H
00014 #include <dmalloc.h>
00015 #endif
00016 #include <sys/types.h>
00017 
00018 #include <net-snmp/types.h>
00019 #include <net-snmp/config_api.h>
00020 
00021 #include <net-snmp/library/snmp_enum.h>
00022 #include <net-snmp/library/tools.h>
00023 
00024 struct snmp_enum_list_str {
00025     char           *name;
00026     struct snmp_enum_list *list;
00027     struct snmp_enum_list_str *next;
00028 };
00029 
00030 static struct snmp_enum_list ***snmp_enum_lists;
00031 unsigned int    current_maj_num;
00032 unsigned int    current_min_num;
00033 struct snmp_enum_list_str *sliststorage;
00034 
00035 int
00036 init_snmp_enum(const char *type)
00037 {
00038     int             i;
00039 
00040     if (!snmp_enum_lists)
00041         snmp_enum_lists = (struct snmp_enum_list ***)
00042             calloc(1, sizeof(struct snmp_enum_list **) * SE_MAX_IDS);
00043     if (!snmp_enum_lists)
00044         return SE_NOMEM;
00045     current_maj_num = SE_MAX_IDS;
00046 
00047     for (i = 0; i < SE_MAX_IDS; i++) {
00048         if (!snmp_enum_lists[i])
00049             snmp_enum_lists[i] = (struct snmp_enum_list **)
00050                 calloc(1, sizeof(struct snmp_enum_list *) * SE_MAX_SUBIDS);
00051         if (!snmp_enum_lists[i])
00052             return SE_NOMEM;
00053     }
00054     current_min_num = SE_MAX_SUBIDS;
00055 
00056     if (!sliststorage)
00057         sliststorage = NULL;
00058 
00059     register_config_handler(type, "enum", se_read_conf, NULL, NULL);
00060     return SE_OK;
00061 }
00062 
00063 int
00064 se_store_in_list(struct snmp_enum_list *new_list,
00065               unsigned int major, unsigned int minor)
00066 {
00067     int             ret = SE_OK;
00068 
00069     if (major > current_maj_num || minor > current_min_num) {
00070         /*
00071          * XXX: realloc 
00072          */
00073         return SE_NOMEM;
00074     }
00075 
00076 
00077     if (snmp_enum_lists[major][minor] != NULL)
00078         ret = SE_ALREADY_THERE;
00079 
00080     snmp_enum_lists[major][minor] = new_list;
00081 
00082     return ret;
00083 }
00084 
00085 void
00086 se_read_conf(const char *word, char *cptr)
00087 {
00088     int major, minor;
00089     int value;
00090     char *cp, *cp2;
00091     char e_name[BUFSIZ];
00092     char e_enum[  BUFSIZ];
00093 
00094     if (!cptr || *cptr=='\0')
00095         return;
00096 
00097     /*
00098      * Extract the first token
00099      *   (which should be the name of the list)
00100      */
00101     cp = copy_nword(cptr, e_name, sizeof(e_name));
00102     cp = skip_white(cp);
00103     if (!cp || *cp=='\0')
00104         return;
00105 
00106 
00107     /*
00108      * Add each remaining enumeration to the list,
00109      *   using the appropriate style interface
00110      */
00111     if (sscanf(e_name, "%d:%d", &major, &minor) == 2) {
00112         /*
00113          *  Numeric major/minor style
00114          */
00115         while (1) {
00116             cp = copy_nword(cp, e_enum, sizeof(e_enum));
00117             if (sscanf(e_enum, "%d:", &value) != 1) {
00118                 break;
00119             }
00120             cp2 = e_enum;
00121             while (*(cp2++) != ':')
00122                 ;
00123             se_add_pair(major, minor, cp2, value);
00124             if (!cp)
00125                 break;
00126         }
00127     } else {
00128         /*
00129          *  Named enumeration
00130          */
00131         while (1) {
00132             cp = copy_nword(cp, e_enum, sizeof(e_enum));
00133             if (sscanf(e_enum, "%d:", &value) != 1) {
00134                 break;
00135             }
00136             cp2 = e_enum;
00137             while (*(cp2++) != ':')
00138                 ;
00139             se_add_pair_to_slist(e_name, cp2, value);
00140             if (!cp)
00141                 break;
00142         }
00143     }
00144 }
00145 
00146 void
00147 se_store_enum_list(struct snmp_enum_list *new_list,
00148                    const char *token, char *type)
00149 {
00150     struct snmp_enum_list *listp = new_list;
00151     char line[2048];
00152     char buf[512];
00153     int  len = 0;
00154 
00155     snprintf(line, sizeof(line), "enum %s", token);
00156     while (listp) {
00157         snprintf(buf, sizeof(buf), " %d:%s", listp->value, listp->label);
00158         /*
00159          * Calculate the space left in the buffer.
00160          * If this is not sufficient to include the next enum,
00161          *   then save the line so far, and start again.
00162          */
00163         len = sizeof(line) - strlen(line);
00164         if ((int)strlen(buf) > len) {
00165             read_config_store(type, line);
00166             snprintf(line, sizeof(line), "enum %s", token);
00167             len = sizeof(line);
00168         }
00169 
00170         strncat(line, buf, len);
00171         listp = listp->next;
00172     }
00173 
00174     /*
00175      * If there's anything left, then save that.
00176      * But don't bother saving an empty 'overflow' line.
00177      */
00178     if (len != sizeof(line))
00179         read_config_store(type, line);
00180 
00181     return;
00182 }
00183 
00184 void
00185 se_store_list(unsigned int major, unsigned int minor, char *type)
00186 {
00187     char token[32];
00188 
00189     snprintf(token, sizeof(token), "%d:%d", major, minor);
00190     se_store_enum_list(se_find_list(major, minor), token, type);
00191 }
00192 
00193 struct snmp_enum_list *
00194 se_find_list(unsigned int major, unsigned int minor)
00195 {
00196     if (major > current_maj_num || minor > current_min_num)
00197         return NULL;
00198 
00199     return snmp_enum_lists[major][minor];
00200 }
00201 
00202 int
00203 se_find_value_in_list(struct snmp_enum_list *list, const char *label)
00204 {
00205     if (!list)
00206         return SE_DNE;          /* XXX: um, no good solution here */
00207     while (list) {
00208         if (strcmp(list->label, label) == 0)
00209             return (list->value);
00210         list = list->next;
00211     }
00212 
00213     return SE_DNE;              /* XXX: um, no good solution here */
00214 }
00215 
00216 int se_remove_value_from_list(struct snmp_enum_list **list, const char *label)
00217 {
00218    struct snmp_enum_list *lastlist;
00219    if(!list)
00220      return SE_DNE;
00221 
00222    lastlist = NULL;
00223    while(*list) {
00224       if(strcmp((*list)->label, label) == 0) {
00225          free((*list)->label);
00226          if(lastlist)
00227            lastlist->next = (*list)->next;
00228          free(*list);
00229          *list = NULL;
00230          return 0;
00231       }
00232       lastlist = *list;
00233       (*list) = (*list)->next;
00234    }
00235    
00236 }
00237 
00238 int
00239 se_find_free_value_in_list(struct snmp_enum_list *list)
00240 {
00241     int max_value = 0;
00242     if (!list)
00243         return SE_DNE;
00244 
00245     for (;list; list=list->next) {
00246         if (max_value < list->value)
00247             max_value = list->value;
00248     }
00249     return max_value+1;
00250 }
00251 
00252 int
00253 se_find_value(unsigned int major, unsigned int minor, const char *label)
00254 {
00255     return se_find_value_in_list(se_find_list(major, minor), label);
00256 }
00257 
00258 int
00259 se_find_free_value(unsigned int major, unsigned int minor)
00260 {
00261     return se_find_free_value_in_list(se_find_list(major, minor));
00262 }
00263 
00264 char           *
00265 se_find_label_in_list(struct snmp_enum_list *list, int value)
00266 {
00267     if (!list)
00268         return NULL;
00269     while (list) {
00270         if (list->value == value)
00271             return (list->label);
00272         list = list->next;
00273     }
00274     return NULL;
00275 }
00276 
00277 char           *
00278 se_find_label(unsigned int major, unsigned int minor, int value)
00279 {
00280     return se_find_label_in_list(se_find_list(major, minor), value);
00281 }
00282 
00283 int
00284 se_add_pair_to_list(struct snmp_enum_list **list, char *label, int value)
00285 {
00286     struct snmp_enum_list *lastnode = NULL;
00287 
00288     if (!list)
00289         return SE_DNE;
00290 
00291     while (*list) {
00292         if ((*list)->value == value)
00293             return (SE_ALREADY_THERE);
00294         lastnode = (*list);
00295         (*list) = (*list)->next;
00296     }
00297 
00298     if (lastnode) {
00299         lastnode->next = SNMP_MALLOC_STRUCT(snmp_enum_list);
00300         lastnode = lastnode->next;
00301     } else {
00302         (*list) = SNMP_MALLOC_STRUCT(snmp_enum_list);
00303         lastnode = (*list);
00304     }
00305     if (!lastnode)
00306         return (SE_NOMEM);
00307     lastnode->label = label;
00308     lastnode->value = value;
00309     lastnode->next = NULL;
00310     return (SE_OK);
00311 }
00312 
00313 int
00314 se_add_pair(unsigned int major, unsigned int minor, char *label, int value)
00315 {
00316     struct snmp_enum_list *list = se_find_list(major, minor);
00317     int             created = (list) ? 1 : 0;
00318     int             ret = se_add_pair_to_list(&list, label, value);
00319     if (!created)
00320         se_store_in_list(list, major, minor);
00321     return ret;
00322 }
00323 
00324 /*
00325  * remember a list of enums based on a lookup name.
00326  */
00327 struct snmp_enum_list *
00328 se_find_slist(const char *listname)
00329 {
00330     struct snmp_enum_list_str *sptr, *lastp = NULL;
00331     if (!listname)
00332         return NULL;
00333 
00334     for (sptr = sliststorage;
00335          sptr != NULL; lastp = sptr, sptr = sptr->next)
00336         if (sptr->name && strcmp(sptr->name, listname) == 0)
00337             return sptr->list;
00338 
00339     return NULL;
00340 }
00341 
00342 
00343 char           *
00344 se_find_label_in_slist(const char *listname, int value)
00345 {
00346     return (se_find_label_in_list(se_find_slist(listname), value));
00347 }
00348 
00349 
00350 int
00351 se_find_value_in_slist(const char *listname, const char *label)
00352 {
00353     return (se_find_value_in_list(se_find_slist(listname), label));
00354 }
00355 
00356 int
00357 se_find_free_value_in_slist(const char *listname)
00358 {
00359     return (se_find_free_value_in_list(se_find_slist(listname)));
00360 }
00361 
00362 void se_remove_value_from_slist(const char *listname, const char *label)
00363 {
00364    struct snmp_enum_list_str *sptr, *lastp = NULL;
00365    struct snmp_enum_list *list;
00366    if (!listname)
00367      return;
00368 
00369    for (sptr = sliststorage;
00370         sptr != NULL; lastp = sptr, sptr = sptr->next)
00371      if (sptr->name && strcmp(sptr->name, listname) == 0)
00372        se_remove_value_from_list(&sptr->list, label);
00373 }
00374 
00375 int
00376 se_add_pair_to_slist(const char *listname, char *label, int value)
00377 {
00378     struct snmp_enum_list *list = se_find_slist(listname);
00379     int             created = (list) ? 1 : 0;
00380     int             ret = se_add_pair_to_list(&list, label, value);
00381 
00382     if (!created) {
00383         struct snmp_enum_list_str *sptr =
00384             SNMP_MALLOC_STRUCT(snmp_enum_list_str);
00385         if (!sptr)
00386             return SE_NOMEM;
00387         sptr->next = sliststorage;
00388         sptr->name = strdup(listname);
00389         sptr->list = list;
00390         sliststorage = sptr;
00391     }
00392     return ret;
00393 }
00394 
00395 void
00396 clear_snmp_enum(void)
00397 {
00398     struct snmp_enum_list_str *sptr = sliststorage, *next = NULL;
00399     struct snmp_enum_list *list = NULL, *nextlist = NULL;
00400     int i;
00401 
00402     while (sptr != NULL) {
00403         next = sptr->next;
00404         list = sptr->list;
00405         while (list != NULL) {
00406             nextlist = list->next;
00407             SNMP_FREE(list->label);
00408             SNMP_FREE(list);
00409             list = nextlist;
00410         }
00411         SNMP_FREE(sptr->name);
00412         SNMP_FREE(sptr);
00413         sptr = next;
00414     }
00415     sliststorage = NULL;
00416 
00417     if (snmp_enum_lists) {
00418         for (i = 0; i < SE_MAX_IDS; i++) {
00419             if (snmp_enum_lists[i])
00420                 SNMP_FREE(snmp_enum_lists[i]);
00421         }
00422         SNMP_FREE(snmp_enum_lists);
00423     }
00424 }
00425 
00426 void
00427 se_clear_list(struct snmp_enum_list **list)
00428 {
00429     struct snmp_enum_list *this_entry, *next_entry;
00430 
00431     if (!list)
00432         return;
00433 
00434     this_entry = *list;
00435     while (this_entry) {
00436         next_entry = this_entry->next;
00437         SNMP_FREE(this_entry->label);
00438         SNMP_FREE(this_entry);
00439         this_entry = next_entry;
00440     }
00441     *list = NULL;
00442     return;
00443 }
00444 
00445 void
00446 se_clear_slist(const char *listname)
00447 {
00448     struct snmp_enum_list *list = se_find_slist(listname);
00449     se_clear_list(&list);
00450 }
00451 
00452 void
00453 se_store_slist(const char *listname, char *type)
00454 {
00455     struct snmp_enum_list *list = se_find_slist(listname);
00456     se_store_enum_list(list, listname, type);
00457 }
00458 
00459 int
00460 se_store_slist_callback(int majorID, int minorID,
00461                         void *serverargs, void *clientargs)
00462 {
00463     char *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00464                                           NETSNMP_DS_LIB_APPTYPE);
00465     se_store_slist((char *)clientargs, appname);
00466     return SNMPERR_SUCCESS;
00467 }
00468 
00469 void
00470 se_clear_all_lists(void)
00471 {
00472     struct snmp_enum_list_str *sptr = NULL;
00473 
00474     for (sptr = sliststorage; sptr != NULL; sptr = sptr->next)
00475         se_clear_list(&(sptr->list));
00476 }
00477 
00478 #ifdef TESTING
00479 main()
00480 {
00481     init_snmp_enum();
00482     se_add_pair(1, 1, "hi", 1);
00483     se_add_pair(1, 1, "there", 2);
00484     printf("hi: %d\n", se_find_value(1, 1, "hi"));
00485     printf("2: %s\n", se_find_label(1, 1, 2));
00486 
00487     se_add_pair_to_slist("testing", "life, and everything", 42);
00488     se_add_pair_to_slist("testing", "resturant at the end of the universe",
00489                          2);
00490 
00491     printf("life, and everything: %d\n",
00492            se_find_value_in_slist("testing", "life, and everything"));
00493     printf("2: %s\n", se_find_label_in_slist("testing", 2));
00494 }
00495 #endif                          /* TESTING */