net-snmp 5.7
|
00001 /* 00002 * netsnmp_data_list.c 00003 * 00004 * $Id$ 00005 */ 00006 #include <net-snmp/net-snmp-config.h> 00007 #include <net-snmp/net-snmp-features.h> 00008 #include <net-snmp/net-snmp-includes.h> 00009 00010 netsnmp_feature_child_of(data_list_all, libnetsnmp) 00011 00012 netsnmp_feature_child_of(data_list_add_data, data_list_all) 00013 netsnmp_feature_child_of(data_list_get_list_node, data_list_all) 00014 00024 NETSNMP_INLINE void 00025 netsnmp_free_list_data(netsnmp_data_list *node) 00026 { 00027 Netsnmp_Free_List_Data *beer; 00028 if (!node) 00029 return; 00030 00031 beer = node->free_func; 00032 if (beer) 00033 (beer) (node->data); 00034 SNMP_FREE(node->name); 00035 } 00036 00040 NETSNMP_INLINE void 00041 netsnmp_free_all_list_data(netsnmp_data_list *head) 00042 { 00043 netsnmp_data_list *tmpptr; 00044 for (; head;) { 00045 netsnmp_free_list_data(head); 00046 tmpptr = head; 00047 head = head->next; 00048 SNMP_FREE(tmpptr); 00049 } 00050 } 00051 00058 NETSNMP_INLINE netsnmp_data_list * 00059 netsnmp_create_data_list(const char *name, void *data, 00060 Netsnmp_Free_List_Data * beer) 00061 { 00062 netsnmp_data_list *node; 00063 00064 if (!name) 00065 return NULL; 00066 node = SNMP_MALLOC_TYPEDEF(netsnmp_data_list); 00067 if (!node) 00068 return NULL; 00069 node->name = strdup(name); 00070 if (!node->name) { 00071 free(node); 00072 return NULL; 00073 } 00074 node->data = data; 00075 node->free_func = beer; 00076 return node; 00077 } 00078 00083 NETSNMP_INLINE void 00084 netsnmp_data_list_add_node(netsnmp_data_list **head, netsnmp_data_list *node) 00085 { 00086 netsnmp_data_list *ptr; 00087 00088 netsnmp_assert(NULL != head); 00089 netsnmp_assert(NULL != node); 00090 netsnmp_assert(NULL != node->name); 00091 00092 DEBUGMSGTL(("data_list","adding key '%s'\n", node->name)); 00093 00094 if (!*head) { 00095 *head = node; 00096 return; 00097 } 00098 00099 if (0 == strcmp(node->name, (*head)->name)) { 00100 netsnmp_assert(!"list key == is unique"); /* always fail */ 00101 snmp_log(LOG_WARNING, 00102 "WARNING: adding duplicate key '%s' to data list\n", 00103 node->name); 00104 } 00105 00106 for (ptr = *head; ptr->next != NULL; ptr = ptr->next) { 00107 netsnmp_assert(NULL != ptr->name); 00108 if (0 == strcmp(node->name, ptr->name)) { 00109 netsnmp_assert(!"list key == is unique"); /* always fail */ 00110 snmp_log(LOG_WARNING, 00111 "WARNING: adding duplicate key '%s' to data list\n", 00112 node->name); 00113 } 00114 } 00115 00116 netsnmp_assert(NULL != ptr); 00117 if (ptr) /* should always be true */ 00118 ptr->next = node; 00119 } 00120 00127 NETSNMP_INLINE void 00128 netsnmp_add_list_data(netsnmp_data_list **head, netsnmp_data_list *node) 00129 { 00130 netsnmp_data_list_add_node(head, node); 00131 } 00132 00140 #ifndef NETSNMP_FEATURE_REMOVE_DATA_LIST_ADD_DATA 00141 NETSNMP_INLINE netsnmp_data_list * 00142 netsnmp_data_list_add_data(netsnmp_data_list **head, const char *name, 00143 void *data, Netsnmp_Free_List_Data * beer) 00144 { 00145 netsnmp_data_list *node; 00146 if (!name) { 00147 snmp_log(LOG_ERR,"no name provided."); 00148 return NULL; 00149 } 00150 node = netsnmp_create_data_list(name, data, beer); 00151 if(NULL == node) { 00152 snmp_log(LOG_ERR,"could not allocate memory for node."); 00153 return NULL; 00154 } 00155 00156 netsnmp_add_list_data(head, node); 00157 00158 return node; 00159 } 00160 #endif /* NETSNMP_FEATURE_REMOVE_DATA_LIST_ADD_DATA */ 00161 00167 NETSNMP_INLINE void * 00168 netsnmp_get_list_data(netsnmp_data_list *head, const char *name) 00169 { 00170 if (!name) 00171 return NULL; 00172 for (; head; head = head->next) 00173 if (head->name && strcmp(head->name, name) == 0) 00174 break; 00175 if (head) 00176 return head->data; 00177 return NULL; 00178 } 00179 00185 #ifndef NETSNMP_FEATURE_REMOVE_DATA_LIST_GET_LIST_NODE 00186 NETSNMP_INLINE netsnmp_data_list * 00187 netsnmp_get_list_node(netsnmp_data_list *head, const char *name) 00188 { 00189 if (!name) 00190 return NULL; 00191 for (; head; head = head->next) 00192 if (head->name && strcmp(head->name, name) == 0) 00193 break; 00194 if (head) 00195 return head; 00196 return NULL; 00197 } 00198 #endif /* NETSNMP_FEATURE_REMOVE_DATA_LIST_GET_LIST_NODE */ 00199 00205 int 00206 netsnmp_remove_list_node(netsnmp_data_list **realhead, const char *name) 00207 { 00208 netsnmp_data_list *head, *prev; 00209 if (!name) 00210 return 1; 00211 for (head = *realhead, prev = NULL; head; 00212 prev = head, head = head->next) { 00213 if (head->name && strcmp(head->name, name) == 0) { 00214 if (prev) 00215 prev->next = head->next; 00216 else 00217 *realhead = head->next; 00218 netsnmp_free_list_data(head); 00219 free(head); 00220 return 0; 00221 } 00222 } 00223 return 1; 00224 } 00225 00227 static netsnmp_data_list *saveHead; 00228 00238 void 00239 netsnmp_register_save_list(netsnmp_data_list **datalist, 00240 const char *type, const char *token, 00241 Netsnmp_Save_List_Data *data_list_save_ptr, 00242 Netsnmp_Read_List_Data *data_list_read_ptr, 00243 Netsnmp_Free_List_Data *data_list_free_ptr) { 00244 netsnmp_data_list_saveinfo *info = 00245 SNMP_MALLOC_TYPEDEF(netsnmp_data_list_saveinfo); 00246 00247 if (!info) { 00248 snmp_log(LOG_ERR, "couldn't malloc a netsnmp_data_list_saveinfo typedef"); 00249 return; 00250 } 00251 00252 info->datalist = datalist; 00253 info->token = token; 00254 info->type = type; 00255 if (!info->type) { 00256 info->type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 00257 NETSNMP_DS_LIB_APPTYPE); 00258 } 00259 00260 /* function which will save the data */ 00261 info->data_list_save_ptr = data_list_save_ptr; 00262 if (data_list_save_ptr) 00263 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, 00264 netsnmp_save_all_data_callback, info); 00265 00266 /* function which will read the data back in */ 00267 info->data_list_read_ptr = data_list_read_ptr; 00268 if (data_list_read_ptr) { 00270 netsnmp_add_list_data(&saveHead, 00271 netsnmp_create_data_list(token, info, NULL)); 00272 register_config_handler(type, token, netsnmp_read_data_callback, 00273 NULL /* XXX */, NULL); 00274 } 00275 00276 info->data_list_free_ptr = data_list_free_ptr; 00277 } 00278 00279 00287 int 00288 netsnmp_save_all_data_callback(int major, int minor, 00289 void *serverarg, void *clientarg) { 00290 netsnmp_data_list_saveinfo *info = (netsnmp_data_list_saveinfo *)clientarg; 00291 00292 if (!clientarg) { 00293 snmp_log(LOG_WARNING, "netsnmp_save_all_data_callback called with no passed data"); 00294 return SNMP_ERR_NOERROR; 00295 } 00296 00297 netsnmp_save_all_data(*(info->datalist), info->type, info->token, 00298 info->data_list_save_ptr); 00299 return SNMP_ERR_NOERROR; 00300 } 00301 00304 int 00305 netsnmp_save_all_data(netsnmp_data_list *head, 00306 const char *type, const char *token, 00307 Netsnmp_Save_List_Data * data_list_save_ptr) 00308 { 00309 char buf[SNMP_MAXBUF], *cp; 00310 00311 for (; head; head = head->next) { 00312 if (head->name) { 00313 /* save begining of line */ 00314 snprintf(buf, sizeof(buf), "%s ", token); 00315 cp = buf + strlen(buf); 00316 cp = read_config_save_octet_string(cp, (u_char*)head->name, 00317 strlen(head->name)); 00318 *cp++ = ' '; 00319 00320 /* call registered function to save the rest */ 00321 if (!(data_list_save_ptr)(cp, 00322 sizeof(buf) - strlen(buf), 00323 head->data)) { 00324 read_config_store(type, buf); 00325 } 00326 } 00327 } 00328 return SNMP_ERR_NOERROR; 00329 } 00330 00340 void 00341 netsnmp_read_data_callback(const char *token, char *line) { 00342 netsnmp_data_list_saveinfo *info; 00343 char *dataname = NULL; 00344 size_t dataname_len; 00345 void *data = NULL; 00346 00347 /* find the stashed information about what we're parsing */ 00348 info = (netsnmp_data_list_saveinfo *) netsnmp_get_list_data(saveHead, token); 00349 if (!info) { 00350 snmp_log(LOG_WARNING, "netsnmp_read_data_callback called without previously registered subparser"); 00351 return; 00352 } 00353 00354 /* read in the token */ 00355 line = 00356 read_config_read_data(ASN_OCTET_STR, line, 00357 &dataname, &dataname_len); 00358 00359 if (!line || !dataname) 00360 return; 00361 00362 /* call the sub-parser to read the rest */ 00363 data = (info->data_list_read_ptr)(line, strlen(line)); 00364 00365 if (!data) { 00366 free(dataname); 00367 return; 00368 } 00369 00370 /* add to the datalist */ 00371 netsnmp_add_list_data(info->datalist, 00372 netsnmp_create_data_list(dataname, data, 00373 info->data_list_free_ptr)); 00374 00375 return; 00376 }