net-snmp
5.4.1
|
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 00217 se_find_free_value_in_list(struct snmp_enum_list *list) 00218 { 00219 int max_value = 0; 00220 if (!list) 00221 return SE_DNE; 00222 00223 for (;list; list=list->next) { 00224 if (max_value < list->value) 00225 max_value = list->value; 00226 } 00227 return max_value+1; 00228 } 00229 00230 int 00231 se_find_value(unsigned int major, unsigned int minor, const char *label) 00232 { 00233 return se_find_value_in_list(se_find_list(major, minor), label); 00234 } 00235 00236 int 00237 se_find_free_value(unsigned int major, unsigned int minor) 00238 { 00239 return se_find_free_value_in_list(se_find_list(major, minor)); 00240 } 00241 00242 char * 00243 se_find_label_in_list(struct snmp_enum_list *list, int value) 00244 { 00245 if (!list) 00246 return NULL; 00247 while (list) { 00248 if (list->value == value) 00249 return (list->label); 00250 list = list->next; 00251 } 00252 return NULL; 00253 } 00254 00255 char * 00256 se_find_label(unsigned int major, unsigned int minor, int value) 00257 { 00258 return se_find_label_in_list(se_find_list(major, minor), value); 00259 } 00260 00261 int 00262 se_add_pair_to_list(struct snmp_enum_list **list, char *label, int value) 00263 { 00264 struct snmp_enum_list *lastnode = NULL; 00265 00266 if (!list) 00267 return SE_DNE; 00268 00269 while (*list) { 00270 if ((*list)->value == value) 00271 return (SE_ALREADY_THERE); 00272 lastnode = (*list); 00273 (*list) = (*list)->next; 00274 } 00275 00276 if (lastnode) { 00277 lastnode->next = SNMP_MALLOC_STRUCT(snmp_enum_list); 00278 lastnode = lastnode->next; 00279 } else { 00280 (*list) = SNMP_MALLOC_STRUCT(snmp_enum_list); 00281 lastnode = (*list); 00282 } 00283 if (!lastnode) 00284 return (SE_NOMEM); 00285 lastnode->label = label; 00286 lastnode->value = value; 00287 lastnode->next = NULL; 00288 return (SE_OK); 00289 } 00290 00291 int 00292 se_add_pair(unsigned int major, unsigned int minor, char *label, int value) 00293 { 00294 struct snmp_enum_list *list = se_find_list(major, minor); 00295 int created = (list) ? 1 : 0; 00296 int ret = se_add_pair_to_list(&list, label, value); 00297 if (!created) 00298 se_store_in_list(list, major, minor); 00299 return ret; 00300 } 00301 00302 /* 00303 * remember a list of enums based on a lookup name. 00304 */ 00305 struct snmp_enum_list * 00306 se_find_slist(const char *listname) 00307 { 00308 struct snmp_enum_list_str *sptr, *lastp = NULL; 00309 if (!listname) 00310 return NULL; 00311 00312 for (sptr = sliststorage; 00313 sptr != NULL; lastp = sptr, sptr = sptr->next) 00314 if (sptr->name && strcmp(sptr->name, listname) == 0) 00315 return sptr->list; 00316 00317 return NULL; 00318 } 00319 00320 00321 char * 00322 se_find_label_in_slist(const char *listname, int value) 00323 { 00324 return (se_find_label_in_list(se_find_slist(listname), value)); 00325 } 00326 00327 00328 int 00329 se_find_value_in_slist(const char *listname, const char *label) 00330 { 00331 return (se_find_value_in_list(se_find_slist(listname), label)); 00332 } 00333 00334 int 00335 se_find_free_value_in_slist(const char *listname) 00336 { 00337 return (se_find_free_value_in_list(se_find_slist(listname))); 00338 } 00339 00340 int 00341 se_add_pair_to_slist(const char *listname, char *label, int value) 00342 { 00343 struct snmp_enum_list *list = se_find_slist(listname); 00344 int created = (list) ? 1 : 0; 00345 int ret = se_add_pair_to_list(&list, label, value); 00346 00347 if (!created) { 00348 struct snmp_enum_list_str *sptr = 00349 SNMP_MALLOC_STRUCT(snmp_enum_list_str); 00350 if (!sptr) 00351 return SE_NOMEM; 00352 sptr->next = sliststorage; 00353 sptr->name = strdup(listname); 00354 sptr->list = list; 00355 sliststorage = sptr; 00356 } 00357 return ret; 00358 } 00359 00360 void 00361 clear_snmp_enum(void) 00362 { 00363 struct snmp_enum_list_str *sptr = sliststorage, *next = NULL; 00364 struct snmp_enum_list *list = NULL, *nextlist = NULL; 00365 int i; 00366 00367 while (sptr != NULL) { 00368 next = sptr->next; 00369 list = sptr->list; 00370 while (list != NULL) { 00371 nextlist = list->next; 00372 SNMP_FREE(list->label); 00373 SNMP_FREE(list); 00374 list = nextlist; 00375 } 00376 SNMP_FREE(sptr->name); 00377 SNMP_FREE(sptr); 00378 sptr = next; 00379 } 00380 sliststorage = NULL; 00381 00382 if (snmp_enum_lists) { 00383 for (i = 0; i < SE_MAX_IDS; i++) { 00384 if (snmp_enum_lists[i]) 00385 SNMP_FREE(snmp_enum_lists[i]); 00386 } 00387 SNMP_FREE(snmp_enum_lists); 00388 } 00389 } 00390 00391 void 00392 se_clear_list(struct snmp_enum_list **list) 00393 { 00394 struct snmp_enum_list *this_entry, *next_entry; 00395 00396 if (!list) 00397 return; 00398 00399 this_entry = *list; 00400 while (this_entry) { 00401 next_entry = this_entry->next; 00402 SNMP_FREE(this_entry->label); 00403 SNMP_FREE(this_entry); 00404 this_entry = next_entry; 00405 } 00406 *list = NULL; 00407 return; 00408 } 00409 00410 void 00411 se_clear_slist(const char *listname) 00412 { 00413 struct snmp_enum_list *list = se_find_slist(listname); 00414 se_clear_list(&list); 00415 } 00416 00417 void 00418 se_store_slist(const char *listname, char *type) 00419 { 00420 struct snmp_enum_list *list = se_find_slist(listname); 00421 se_store_enum_list(list, listname, type); 00422 } 00423 00424 int 00425 se_store_slist_callback(int majorID, int minorID, 00426 void *serverargs, void *clientargs) 00427 { 00428 char *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 00429 NETSNMP_DS_LIB_APPTYPE); 00430 se_store_slist((char *)clientargs, appname); 00431 return SNMPERR_SUCCESS; 00432 } 00433 00434 void 00435 se_clear_all_lists(void) 00436 { 00437 struct snmp_enum_list_str *sptr = NULL; 00438 00439 for (sptr = sliststorage; sptr != NULL; sptr = sptr->next) 00440 se_clear_list(&(sptr->list)); 00441 } 00442 00443 #ifdef TESTING 00444 main() 00445 { 00446 init_snmp_enum(); 00447 se_add_pair(1, 1, "hi", 1); 00448 se_add_pair(1, 1, "there", 2); 00449 printf("hi: %d\n", se_find_value(1, 1, "hi")); 00450 printf("2: %s\n", se_find_label(1, 1, 2)); 00451 00452 se_add_pair_to_slist("testing", "life, and everything", 42); 00453 se_add_pair_to_slist("testing", "resturant at the end of the universe", 00454 2); 00455 00456 printf("life, and everything: %d\n", 00457 se_find_value_in_slist("testing", "life, and everything")); 00458 printf("2: %s\n", se_find_label_in_slist("testing", 2)); 00459 } 00460 #endif /* TESTING */