net-snmp
5.4.1
|
00001 /* 00002 * netsnmp_data_list.c 00003 * 00004 * $Id: data_list.c 16612 2007-07-16 23:59:44Z hardaker $ 00005 */ 00006 #include <net-snmp/net-snmp-config.h> 00007 #include <net-snmp/net-snmp-includes.h> 00008 00009 /* 00010 * prototypes 00011 */ 00012 NETSNMP_INLINE void 00013 netsnmp_data_list_add_node(netsnmp_data_list **head, netsnmp_data_list *node); 00014 00015 00025 NETSNMP_INLINE void 00026 netsnmp_free_list_data(netsnmp_data_list *node) 00027 { 00028 Netsnmp_Free_List_Data *beer; 00029 if (!node) 00030 return; 00031 00032 beer = node->free_func; 00033 if (beer) 00034 (beer) (node->data); 00035 SNMP_FREE(node->name); 00036 } 00037 00041 NETSNMP_INLINE void 00042 netsnmp_free_all_list_data(netsnmp_data_list *head) 00043 { 00044 netsnmp_data_list *tmpptr; 00045 for (; head;) { 00046 netsnmp_free_list_data(head); 00047 tmpptr = head; 00048 head = head->next; 00049 SNMP_FREE(tmpptr); 00050 } 00051 } 00052 00059 NETSNMP_INLINE netsnmp_data_list * 00060 netsnmp_create_data_list(const char *name, void *data, 00061 Netsnmp_Free_List_Data * beer) 00062 { 00063 netsnmp_data_list *node; 00064 00065 if (!name) 00066 return NULL; 00067 node = SNMP_MALLOC_TYPEDEF(netsnmp_data_list); 00068 if (!node) 00069 return NULL; 00070 node->name = strdup(name); 00071 node->data = data; 00072 node->free_func = beer; 00073 return node; 00074 } 00075 00082 NETSNMP_INLINE void 00083 netsnmp_add_list_data(netsnmp_data_list **head, netsnmp_data_list *node) 00084 { 00085 netsnmp_data_list_add_node(head, node); 00086 } 00087 00092 NETSNMP_INLINE void 00093 netsnmp_data_list_add_node(netsnmp_data_list **head, netsnmp_data_list *node) 00094 { 00095 netsnmp_data_list *ptr; 00096 00097 netsnmp_assert(NULL != head); 00098 netsnmp_assert(NULL != node); 00099 netsnmp_assert(NULL != node->name); 00100 00101 if (!*head) { 00102 *head = node; 00103 return; 00104 } 00105 00106 DEBUGMSGTL(("data_list","adding key '%s'\n", node->name)); 00107 if (0 == strcmp(node->name, (*head)->name)) { 00108 netsnmp_assert(!"list key == is unique"); /* always fail */ 00109 snmp_log(LOG_WARNING, 00110 "WARNING: adding duplicate key '%s' to data list\n", 00111 node->name); 00112 } 00113 00114 for (ptr = *head; ptr->next != NULL; ptr = ptr->next) { 00115 netsnmp_assert(NULL != ptr->name); 00116 if (0 == strcmp(node->name, ptr->name)) { 00117 netsnmp_assert(!"list key == is unique"); /* always fail */ 00118 snmp_log(LOG_WARNING, 00119 "WARNING: adding duplicate key '%s' to data list\n", 00120 node->name); 00121 } 00122 } 00123 00124 netsnmp_assert(NULL != ptr); 00125 if (ptr) /* should always be true */ 00126 ptr->next = node; 00127 } 00128 00136 NETSNMP_INLINE netsnmp_data_list * 00137 netsnmp_data_list_add_data(netsnmp_data_list **head, const char *name, 00138 void *data, Netsnmp_Free_List_Data * beer) 00139 { 00140 netsnmp_data_list *node; 00141 if (!name) { 00142 snmp_log(LOG_ERR,"no name provided."); 00143 return NULL; 00144 } 00145 node = netsnmp_create_data_list(name, data, beer); 00146 if(NULL == node) { 00147 snmp_log(LOG_ERR,"could not allocate memory for node."); 00148 return NULL; 00149 } 00150 00151 netsnmp_add_list_data(head, node); 00152 00153 return node; 00154 } 00155 00161 NETSNMP_INLINE void * 00162 netsnmp_get_list_data(netsnmp_data_list *head, const char *name) 00163 { 00164 if (!name) 00165 return NULL; 00166 for (; head; head = head->next) 00167 if (head->name && strcmp(head->name, name) == 0) 00168 break; 00169 if (head) 00170 return head->data; 00171 return NULL; 00172 } 00173 00179 NETSNMP_INLINE netsnmp_data_list * 00180 netsnmp_get_list_node(netsnmp_data_list *head, const char *name) 00181 { 00182 if (!name) 00183 return NULL; 00184 for (; head; head = head->next) 00185 if (head->name && strcmp(head->name, name) == 0) 00186 break; 00187 if (head) 00188 return head; 00189 return NULL; 00190 } 00191 00197 int 00198 netsnmp_remove_list_node(netsnmp_data_list **realhead, const char *name) 00199 { 00200 netsnmp_data_list *head, *prev; 00201 if (!name) 00202 return 1; 00203 for (head = *realhead, prev = NULL; head; 00204 prev = head, head = head->next) { 00205 if (head->name && strcmp(head->name, name) == 0) { 00206 if (prev) 00207 prev->next = head->next; 00208 else 00209 *realhead = head->next; 00210 netsnmp_free_list_data(head); 00211 free(head); 00212 return 0; 00213 } 00214 } 00215 return 1; 00216 } 00217 00219 static netsnmp_data_list *saveHead; 00220 00230 void 00231 netsnmp_register_save_list(netsnmp_data_list **datalist, 00232 const char *type, const char *token, 00233 Netsnmp_Save_List_Data *data_list_save_ptr, 00234 Netsnmp_Read_List_Data *data_list_read_ptr, 00235 Netsnmp_Free_List_Data *data_list_free_ptr) { 00236 netsnmp_data_list_saveinfo *info = 00237 SNMP_MALLOC_TYPEDEF(netsnmp_data_list_saveinfo); 00238 00239 if (!info) { 00240 snmp_log(LOG_ERR, "couldn't malloc a netsnmp_data_list_saveinfo typedef"); 00241 return; 00242 } 00243 00244 info->datalist = datalist; 00245 info->token = token; 00246 info->type = type; 00247 if (!info->type) { 00248 info->type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 00249 NETSNMP_DS_LIB_APPTYPE); 00250 } 00251 00252 /* function which will save the data */ 00253 info->data_list_save_ptr = data_list_save_ptr; 00254 if (data_list_save_ptr) 00255 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, 00256 netsnmp_save_all_data_callback, info); 00257 00258 /* function which will read the data back in */ 00259 info->data_list_read_ptr = data_list_read_ptr; 00260 if (data_list_read_ptr) { 00262 netsnmp_add_list_data(&saveHead, 00263 netsnmp_create_data_list(token, info, NULL)); 00264 register_config_handler(type, token, netsnmp_read_data_callback, 00265 NULL /* XXX */, NULL); 00266 } 00267 00268 info->data_list_free_ptr = data_list_free_ptr; 00269 } 00270 00271 00279 int 00280 netsnmp_save_all_data_callback(int major, int minor, 00281 void *serverarg, void *clientarg) { 00282 netsnmp_data_list_saveinfo *info = (netsnmp_data_list_saveinfo *)clientarg; 00283 00284 if (!clientarg) { 00285 snmp_log(LOG_WARNING, "netsnmp_save_all_data_callback called with no passed data"); 00286 return SNMP_ERR_NOERROR; 00287 } 00288 00289 netsnmp_save_all_data(*(info->datalist), info->type, info->token, 00290 info->data_list_save_ptr); 00291 return SNMP_ERR_NOERROR; 00292 } 00293 00296 int 00297 netsnmp_save_all_data(netsnmp_data_list *head, 00298 const char *type, const char *token, 00299 Netsnmp_Save_List_Data * data_list_save_ptr) 00300 { 00301 char buf[SNMP_MAXBUF], *cp; 00302 00303 for (; head; head = head->next) { 00304 if (head->name) { 00305 /* save begining of line */ 00306 snprintf(buf, sizeof(buf), "%s ", token); 00307 cp = buf + strlen(buf); 00308 cp = read_config_save_octet_string(cp, (u_char*)head->name, 00309 strlen(head->name)); 00310 *cp++ = ' '; 00311 00312 /* call registered function to save the rest */ 00313 if (!(data_list_save_ptr)(cp, 00314 sizeof(buf) - strlen(buf), 00315 head->data)) { 00316 read_config_store(type, buf); 00317 } 00318 } 00319 } 00320 return SNMP_ERR_NOERROR; 00321 } 00322 00331 void 00332 netsnmp_read_data_callback(const char *token, char *line) { 00333 netsnmp_data_list_saveinfo *info; 00334 char *dataname = NULL; 00335 size_t dataname_len; 00336 void *data = NULL; 00337 00338 /* find the stashed information about what we're parsing */ 00339 info = (netsnmp_data_list_saveinfo *) netsnmp_get_list_data(saveHead, token); 00340 if (!info) { 00341 snmp_log(LOG_WARNING, "netsnmp_read_data_callback called without previously registered subparser"); 00342 return; 00343 } 00344 00345 /* read in the token */ 00346 line = 00347 read_config_read_data(ASN_OCTET_STR, line, 00348 &dataname, &dataname_len); 00349 00350 if (!line || !dataname) 00351 return; 00352 00353 /* call the sub-parser to read the rest */ 00354 data = (info->data_list_read_ptr)(line, strlen(line)); 00355 00356 if (!data) { 00357 free(dataname); 00358 return; 00359 } 00360 00361 /* add to the datalist */ 00362 netsnmp_add_list_data(info->datalist, 00363 netsnmp_create_data_list(dataname, data, 00364 info->data_list_free_ptr)); 00365 00366 return; 00367 }