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