static int _cache_load(netsnmp_cache *cache, netsnmp_tdata *table) { netsnmp_container *maps; netsnmp_iterator *map_itr; netsnmp_cert_map *map; netsnmp_tdata_row *row; certToTSN_entry *entry; int rc = 0; DEBUGMSGTL(("tlstmCertToTSNTable:cache:load", "called, %" NETSNMP_PRIz "d rows\n", CONTAINER_SIZE(table->container))); /** get current active maps */ maps = netsnmp_cert_map_container(); if (NULL == maps) return 0; DEBUGMSGTL(("tlstmCertToTSNTable:cache:load", "maps %" NETSNMP_PRIz "d rows\n", CONTAINER_SIZE(maps))); map_itr = CONTAINER_ITERATOR(maps); if (NULL == map_itr) { DEBUGMSGTL(("tlstmCertToTSNTable:cache:load", "cant get map iterator\n")); return -1; } /* * insert rows for active maps into tbl container */ map = ITERATOR_FIRST(map_itr); for( ; map; map = ITERATOR_NEXT(map_itr)) { row = _entry_from_map(map); if (NULL == row) { rc =-1; break; } entry = (certToTSN_entry*)row->data; entry->rowStatus = RS_ACTIVE; if (netsnmp_tdata_add_row(table, row) != SNMPERR_SUCCESS) { tlstmCertToTSNTable_removeEntry(NULL, row); rc = -1; break; } } ITERATOR_RELEASE(map_itr); DEBUGMSGTL(("tlstmCertToTSNTable:cache:load", "done, %" NETSNMP_PRIz "d rows\n", CONTAINER_SIZE(table->container))); return rc; }
/** * * @retval 0 no errors * @retval !0 errors */ static int _load6(netsnmp_container *container, u_int load_flags) { netsnmp_file *fp; netsnmp_line_process_info lpi; if (NULL == container) return -1; /* * allocate file resources */ fp = netsnmp_file_fill(NULL, "/proc/net/udp6" , O_RDONLY, 0, 0); if (NULL == fp) /** msg already logged */ return -2; memset(&lpi, 0x0, sizeof(lpi)); lpi.mem_size = sizeof(netsnmp_udp_endpoint_entry); lpi.process = _process_line_udp_ep; lpi.user_context = (void*)CONTAINER_SIZE(container); container = netsnmp_file_text_parse(fp, container, PM_USER_FUNCTION, 0, &lpi); netsnmp_file_release(fp); return (NULL == container); }
/* * sql cleanup function, called at exit */ static void netsnmp_mysql_cleanup(void) { DEBUGMSGTL(("sql:cleanup"," called\n")); /** unregister alarm */ if (_sql.alarm_id) snmp_alarm_unregister(_sql.alarm_id); /** save any queued traps */ if (CONTAINER_SIZE(_sql.queue)) _sql_process_queue(0,NULL); CONTAINER_FREE(_sql.queue); _sql.queue = NULL; if (_sql.trap_stmt) { mysql_stmt_close(_sql.trap_stmt); _sql.trap_stmt = NULL; } if (_sql.vb_stmt) { mysql_stmt_close(_sql.vb_stmt); _sql.vb_stmt = NULL; } /** disconnect from server */ netsnmp_sql_disconnected(); if (_sql.conn) { mysql_close(_sql.conn); _sql.conn = NULL; } mysql_library_end(); }
static int _count_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { int val; if (MODE_GET != reqinfo->mode) { snmp_log(LOG_ERR, "bad mode in RO handler"); return SNMP_ERR_GENERR; } if (NULL == _table->container) val = 0; else val = CONTAINER_SIZE(_table->container); snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &val, sizeof(val)); if (handler->next && handler->next->access_method) return netsnmp_call_next_handler(handler, reginfo, reqinfo, requests); return SNMP_ERR_NOERROR; }
int netsnmp_tdata_row_count(netsnmp_tdata *table) { if (!table) return 0; return CONTAINER_SIZE( table->container ); }
int delete_watchdog_row (SaHpiDomainIdT domain_id, SaHpiResourceIdT resource_id, SaHpiWatchdogNumT num) { saHpiWatchdogTable_context *ctx; oid index_oid[WATCHDOG_INDEX_NR]; netsnmp_index index; int rc = AGENT_ERR_NOT_FOUND; DEBUGMSGTL ((AGENT, "delete_watchdog_row (%d, %d, %d). Entry.\n", domain_id, resource_id, num)); // Look at the MIB to find out what the indexs are index_oid[0] = domain_id; index_oid[1] = resource_id; index_oid[2] = num; // Possible more indexes? index.oids = (oid *) & index_oid; index.len = WATCHDOG_INDEX_NR; ctx = CONTAINER_FIND (cb.container, &index); if (ctx) { CONTAINER_REMOVE (cb.container, ctx); saHpiWatchdogTable_delete_row (ctx); watchdog_count = CONTAINER_SIZE (cb.container); rc = AGENT_ERR_NOERROR; } DEBUGMSGTL ((AGENT, "delete_watchdog_row. Exit (rc: %d).\n", rc)); return rc; }
/** * * @handler: * @reginfo: * @reqinfo: * @requests: * * @return: */ int handle_saHpiDomainEventEntryCount(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { /* We are never called for a GETNEXT if it's registered as a "instance", as it's "magically" handled for us. */ /* a instance handler also only hands us one request at a time, so we don't need to loop over a list of requests; we'll only get one. */ DEBUGMSGTL ((AGENT, "handle_saHpiDomainEventEntryCount, called\n")); domain_event_entry_count = CONTAINER_SIZE (cb.container); switch(reqinfo->mode) { case MODE_GET: snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER, (u_char *) &domain_event_entry_count, sizeof(domain_event_entry_count)); break; default: /* we should never get here, so this is a really bad error */ return SNMP_ERR_GENERR; } return SNMP_ERR_NOERROR; }
/** * load initial data * * TODO:350:M: Implement tcpListenerTable data load * This function will also be called by the cache helper to load * the container again (after the container free function has been * called to free the previous contents). * * @param container container to which items should be inserted * * @retval MFD_SUCCESS : success. * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source * @retval MFD_ERROR : other error. * * This function is called to load the index(es) (and data, optionally) * for the every row in the data set. * * @remark * While loading the data, the only important thing is the indexes. * If access to your data is cheap/fast (e.g. you have a pointer to a * structure in memory), it would make sense to update the data here. * If, however, the accessing the data invovles more work (e.g. parsing * some other existing data, or peforming calculations to derive the data), * then you can limit yourself to setting the indexes and saving any * information you will need later. Then use the saved information in * tcpListenerTable_row_prep() for populating data. * * @note * If you need consistency between rows (like you want statistics * for each row to be from the same time frame), you should set all * data here. * */ int tcpListenerTable_container_load(netsnmp_container *container) { netsnmp_container *raw_data = netsnmp_access_tcpconn_container_load(NULL, NETSNMP_ACCESS_TCPCONN_LOAD_ONLYLISTEN); DEBUGMSGTL(("verbose:tcpListenerTable:tcpListenerTable_container_load", "called\n")); if (NULL == raw_data) return MFD_RESOURCE_UNAVAILABLE; /* msg already logged */ /* * got all the connections. pull out the active ones. */ CONTAINER_FOR_EACH(raw_data, (netsnmp_container_obj_func *) _add_connection, container); /* * free the container. we've either claimed each entry, or released it, * so the dal function doesn't need to clear the container. */ netsnmp_access_tcpconn_container_free(raw_data, 0); DEBUGMSGT(("verbose:tcpListenerTable:tcpListenerTable_cache_load", "%d records\n", (int)CONTAINER_SIZE(container))); return MFD_SUCCESS; } /* tcpListenerTable_container_load */
/** * * @sessionid * * @return */ SaErrorT clear_domain_info_entry(SaHpiDomainIdT domain_id) { SaErrorT rv = SA_OK; netsnmp_index *row_idx; saHpiDomainInfoTable_context *ctx; DEBUGMSGTL ((AGENT, "clear_domain_info_entry, called\n")); DEBUGMSGTL ((AGENT, " domainId [%d]\n", domain_id)); row_idx = CONTAINER_FIRST(cb.container); if (row_idx) //At least one entry was found. { do { ctx = CONTAINER_FIND(cb.container, row_idx); row_idx = CONTAINER_NEXT(cb.container, row_idx); if (ctx->index.oids[saHpiDomainId_INDEX] == domain_id) { /* all conditions met remove row */ CONTAINER_REMOVE (cb.container, ctx); saHpiDomainInfoTable_delete_row (ctx); domain_info_entry_count = CONTAINER_SIZE (cb.container); DEBUGMSGTL ((AGENT, "clear_domain_info_entry:" " found row: removing\n")); } } while (row_idx); } return rv; }
/* --------------------------------------------------------------------- */ int netsnmp_swinst_arch_load( netsnmp_container *container, u_int flags) { /* Nothing to do */ DEBUGMSGTL(("swinst:load:arch"," loaded %" NETSNMP_PRIz "d entries\n", CONTAINER_SIZE(container))); return 0; }
static int _load_udp_endpoint_table_v6(netsnmp_container *container, int flag) { netsnmp_udp_endpoint_entry *ep; mib2_udp6Entry_t ue6; req_e req = GET_FIRST; DEBUGMSGT(("access:udp_endpoint:container", "load v6\n")); while (getMibstat(MIB_UDP6_ENDPOINT, &ue6, sizeof(ue6), req, &Get_everything, 0)==0) { req = GET_NEXT; ep = netsnmp_access_udp_endpoint_entry_create(); if (ep == NULL) return (-1); DEBUGMSGT(("access:udp_endpoint:container", "add entry\n")); /* * local address/port. */ ep->loc_addr_len = sizeof(ue6.udp6LocalAddress); if (sizeof(ep->loc_addr) < ep->loc_addr_len) { netsnmp_access_udp_endpoint_entry_free(ep); return (-1); } (void)memcpy(&ep->loc_addr, &ue6.udp6LocalAddress, ep->loc_addr_len); ep->loc_port = ue6.udp6LocalPort; /* remote address/port */ if (IN6_IS_ADDR_UNSPECIFIED(&ue6.udp6EntryInfo.ue_RemoteAddress)) { ep->rmt_addr_len = 0; } else { ep->rmt_addr_len = sizeof(ue6.udp6EntryInfo.ue_RemoteAddress); (void)memcpy(&ep->rmt_addr, &ue6.udp6EntryInfo.ue_RemoteAddress, ep->rmt_addr_len); } ep->rmt_port = ue6.udp6EntryInfo.ue_RemotePort; /* instance */ #ifdef SOLARIS_HAVE_RFC4293_SUPPORT ep->instance = ue6.udp6Instance; #else ep->instance = 0; #endif /* state */ ep->state = 0; /* index */ ep->index = CONTAINER_SIZE(container) + 1; ep->oid_index.oids = &ep->index; ep->oid_index.len = 1; CONTAINER_INSERT(container, (void *)ep); } return (0); }
/** * * @retval 0 no errors * @retval !0 errors */ static int _kvmload(netsnmp_container *container, u_int load_flags) { netsnmp_udp_endpoint_entry *entry; struct kinfo_file *kf; int count; int rc = 0; kf = kvm_getfiles(kd, KERN_FILE_BYFILE, DTYPE_SOCKET, sizeof(struct kinfo_file), &count); while (count--) { if (kf->so_protocol != IPPROTO_UDP) goto skip; #if !defined(NETSNMP_ENABLE_IPV6) if (kf->so_family == AF_INET6) goto skip; #endif entry = netsnmp_access_udp_endpoint_entry_create(); if(NULL == entry) { rc = -3; break; } /** oddly enough, these appear to already be in network order */ entry->loc_port = ntohs(kf->inp_lport); entry->rmt_port = ntohs(kf->inp_fport); entry->pid = kf->p_pid; /** the addr string may need work */ if (kf->so_family == AF_INET6) { entry->loc_addr_len = entry->rmt_addr_len = 16; memcpy(entry->loc_addr, &kf->inp_laddru, 16); memcpy(entry->rmt_addr, &kf->inp_faddru, 16); } else { entry->loc_addr_len = entry->rmt_addr_len = 4; memcpy(entry->loc_addr, &kf->inp_laddru[0], 4); memcpy(entry->rmt_addr, &kf->inp_faddru[0], 4); } DEBUGMSGTL(("udp-mib/data_access", "udp %d %d %d\n", entry->loc_addr_len, entry->loc_port, entry->rmt_port)); /* * add entry to container */ entry->index = CONTAINER_SIZE(container) + 1; CONTAINER_INSERT(container, entry); skip: kf++; } if (rc < 0) return rc; return 0; }
/** * load initial data * * TODO:350:M: Implement inetCidrRouteTable data load * This function will also be called by the cache helper to load * the container again (after the container free function has been * called to free the previous contents). * * @param container container to which items should be inserted * * @retval MFD_SUCCESS : success. * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source * @retval MFD_ERROR : other error. * * This function is called to load the index(es) (and data, optionally) * for the every row in the data set. * * @remark * While loading the data, the only important thing is the indexes. * If access to your data is cheap/fast (e.g. you have a pointer to a * structure in memory), it would make sense to update the data here. * If, however, the accessing the data invovles more work (e.g. parsing * some other existing data, or peforming calculations to derive the data), * then you can limit yourself to setting the indexes and saving any * information you will need later. Then use the saved information in * inetCidrRouteTable_row_prep() for populating data. * * @note * If you need consistency between rows (like you want statistics * for each row to be from the same time frame), you should set all * data here. * */ int inetCidrRouteTable_container_load(netsnmp_container *container) { netsnmp_container *route_container; DEBUGMSGTL(("verbose:inetCidrRouteTable:inetCidrRouteTable_container_load", "called\n")); /* * TODO:351:M: |-> Load/update data in the inetCidrRouteTable container. * loop over your inetCidrRouteTable data, allocate a rowreq context, * set the index(es) [and data, optionally] and insert into * the container. * * we use the netsnmp data access api to get the data */ route_container = netsnmp_access_route_container_load(NULL, NETSNMP_ACCESS_ROUTE_LOAD_NOFLAGS); DEBUGMSGT(("verbose:inetCidrRouteTable:inetCidrRouteTable_cache_load", "%d records\n", (int)CONTAINER_SIZE(route_container))); if (NULL == route_container) return MFD_RESOURCE_UNAVAILABLE; /* msg already logged */ /* * we just got a fresh copy of route data. snarf data */ CONTAINER_FOR_EACH(route_container, (netsnmp_container_obj_func *) _snarf_route_entry, container); /* * free the container. we've either claimed each ifentry, or released it, * so the dal function doesn't need to clear the container. */ netsnmp_access_route_container_free(route_container, NETSNMP_ACCESS_ROUTE_FREE_DONT_CLEAR); DEBUGMSGT(("verbose:inetCidrRouteTable:inetCidrRouteTable_cache_load", "%d records\n", (int)CONTAINER_SIZE(container))); return MFD_SUCCESS; } /* inetCidrRouteTable_container_load */
static int _load_tcpconn_table_v4(netsnmp_container *container, int flag) { mib2_tcpConnEntry_t tc; netsnmp_tcpconn_entry *ep; req_e req = GET_FIRST; DEBUGMSGT(("access:tcpconn:container", "load v4\n")); while (getMibstat(MIB_TCP_CONN, &tc, sizeof(tc), req, &Get_everything, 0)==0) { req = GET_NEXT; if ((flag & NETSNMP_ACCESS_TCPCONN_LOAD_ONLYLISTEN && tc.tcpConnState != MIB2_TCP_listen) || (flag & NETSNMP_ACCESS_TCPCONN_LOAD_NOLISTEN && tc.tcpConnState == MIB2_TCP_listen)) { continue; } ep = netsnmp_access_tcpconn_entry_create(); if (ep == NULL) return (-1); DEBUGMSGT(("access:tcpconn:container", "add entry\n")); /* * local address/port. */ ep->loc_addr_len = sizeof(tc.tcpConnLocalAddress); if (sizeof(ep->loc_addr) < ep->loc_addr_len) { netsnmp_access_tcpconn_entry_free(ep); return (-1); } (void)memcpy(&ep->loc_addr, &tc.tcpConnLocalAddress, ep->loc_addr_len); ep->loc_port = tc.tcpConnLocalPort; /* * remote address/port. The address length is the same as the * local address, so no check needed. */ ep->rmt_addr_len = sizeof(tc.tcpConnRemAddress); (void)memcpy(&ep->rmt_addr, &tc.tcpConnRemAddress, ep->rmt_addr_len); ep->rmt_port = tc.tcpConnRemPort; /* state/pid */ ep->tcpConnState = tc.tcpConnState; ep->pid = 0; ep->arch_data = NULL; /* index */ ep->arbitrary_index = CONTAINER_SIZE(container) + 1; CONTAINER_INSERT(container, (void *)ep); } return (0); }
/** * load initial data * * TODO:350:M: Implement ifTable data load * This function will also be called by the cache helper to load * the container again (after the container free function has been * called to free the previous contents). * * @param container container to which items should be inserted * * @retval MFD_SUCCESS : success. * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source * @retval MFD_ERROR : other error. * * This function is called to load the index(es) (and data, optionally) * for the every row in the data set. * * @remark * While loading the data, the only important thing is the indexes. * If access to your data is cheap/fast (e.g. you have a pointer to a * structure in memory), it would make sense to update the data here. * If, however, the accessing the data invovles more work (e.g. parsing * some other existing data, or peforming calculations to derive the data), * then you can limit yourself to setting the indexes and saving any * information you will need later. Then use the saved information in * ifTable_row_prep() for populating data. * * @note * If you need consistency between rows (like you want statistics * for each row to be from the same time frame), you should set all * data here. * */ int ifTable_container_load(netsnmp_container *container) { netsnmp_container *ifcontainer; DEBUGMSGTL(("verbose:ifTable:ifTable_container_load", "called\n")); /* * TODO:351:M: |-> Load/update data in the ifTable container. * loop over your ifTable data, allocate a rowreq context, * set the index(es) [and data, optionally] and insert into * the container. */ /* * ifTable gets its data from the netsnmp_interface API. */ ifcontainer = netsnmp_access_interface_container_load(NULL, NETSNMP_ACCESS_INTERFACE_INIT_NOFLAGS); if (NULL == ifcontainer) return MFD_RESOURCE_UNAVAILABLE; /* msg already logged */ /* * we just got a fresh copy of interface data. compare it to * what we've already got, and make any adjustements... */ CONTAINER_FOR_EACH(container, (netsnmp_container_obj_func *) _check_interface_entry_for_updates, ifcontainer); /* * now add any new interfaces */ CONTAINER_FOR_EACH(ifcontainer, (netsnmp_container_obj_func *) _add_new_interface, container); /* * free the container. we've either claimed each ifentry, or released it, * so the dal function doesn't need to clear the container. */ netsnmp_access_interface_container_free(ifcontainer, NETSNMP_ACCESS_INTERFACE_FREE_DONT_CLEAR); DEBUGMSGT(("verbose:ifTable:ifTable_cache_load", "%d records\n", CONTAINER_SIZE(container))); if (_first_load) _first_load = 0; return MFD_SUCCESS; } /* ifTable_container_load */
static void _cache_free(netsnmp_cache *cache, netsnmp_tdata *table) { netsnmp_tdata_row *row; netsnmp_iterator *tbl_itr; certToTSN_entry *entry; DEBUGMSGTL(("tlstmCertToTSNTable:cache:free", "called, %" NETSNMP_PRIz "d rows\n", CONTAINER_SIZE(table->container))); /** insert rows for active maps into tbl container */ tbl_itr = CONTAINER_ITERATOR(table->container); if (NULL == tbl_itr) { DEBUGMSGTL(("tlstmCertToTSNTable:cache:free", "cant get map iterator\n")); return; } row = ITERATOR_FIRST(tbl_itr); for( ; row; row = ITERATOR_NEXT(tbl_itr)) { entry = row->data; /* * remove all active rows (they are in the maps container kept * by the library). Keep inactive ones for next time. */ if (entry->rowStatus == RS_ACTIVE) { tlstmCertToTSNTable_removeEntry(NULL, row); ITERATOR_REMOVE(tbl_itr); continue; } } ITERATOR_RELEASE(tbl_itr); DEBUGMSGTL(("tlstmCertToTSNTable:cache:free", "done, %" NETSNMP_PRIz "d rows\n", CONTAINER_SIZE(table->container))); }
/* * process (save) queued items to sql database. * * dontcare & meeither are dummy params so this function can be used * as a netsnmp_alarm callback function. */ static void _sql_process_queue(u_int dontcare, void *meeither) { int rc; /** bail if the queue is empty */ if( 0 == CONTAINER_SIZE(_sql.queue)) return; DEBUGMSGT(("sql:process", "processing %d queued traps\n", (int)CONTAINER_SIZE(_sql.queue))); /* * if we don't have a database connection, try to reconnect. We * don't care if we fail - traps will be logged in that case. */ if (0 == _sql.connected) { DEBUGMSGT(("sql:process", "no sql connection; reconnecting\n")); (void) netsnmp_mysql_connect(); } CONTAINER_FOR_EACH(_sql.queue, (netsnmp_container_obj_func*)_sql_save, NULL); if (_sql.connected) { rc = mysql_commit(_sql.conn); if (rc) { /* nuts... now what? */ netsnmp_sql_error("commit failed"); CONTAINER_FOR_EACH(_sql.queue, (netsnmp_container_obj_func*)_sql_log, NULL); } } CONTAINER_CLEAR(_sql.queue, (netsnmp_container_obj_func*)_sql_buf_free, NULL); }
/* * Remove all entries from sctpAssocRemAddrTable, which are not marked as valid. * All valid entries are then marked as invalid (to delete them in next cache * load, if the entry is not updated). */ void sctpAssocRemAddrTable_delete_invalid(netsnmp_container *remAddrTable) { netsnmp_container *to_delete = netsnmp_container_find("lifo"); CONTAINER_FOR_EACH(remAddrTable, sctpAssocRemAddrTable_collect_invalid, to_delete); while (CONTAINER_SIZE(to_delete)) { sctpAssocRemAddrTable_entry *entry = CONTAINER_FIRST(to_delete); CONTAINER_REMOVE(remAddrTable, entry); sctpAssocRemAddrTable_entry_free(entry); CONTAINER_REMOVE(to_delete, NULL); } CONTAINER_FREE(to_delete); }
/* --------------------------------------------------------------------- */ int netsnmp_swinst_arch_load( netsnmp_container *container, u_int flags) { FILE *p = popen("dpkg-query --show --showformat '${Package}#${Version}#${Section}#${Priority}#${Essential}#${Status}\n'", "r"); char package[SNMP_MAXBUF]; char version[SNMP_MAXBUF]; char section[SNMP_MAXBUF]; char priority[SNMP_MAXBUF]; char essential[SNMP_MAXBUF]; char status[SNMP_MAXBUF]; char buf[BUFSIZ]; netsnmp_swinst_entry *entry; int i = 0; if (p == NULL) { snmp_perror("dpkg-list"); return 1; } while (fgets(buf, BUFSIZ, p)) { DEBUGMSG(("swinst_apt", "entry: %s\n", buf)); entry = netsnmp_swinst_entry_create( i++ ); if (NULL == entry) continue; /* error already logged by function */ CONTAINER_INSERT(container, entry); sscanf(buf, apt_fmt, package, version, section, priority, essential, status); if (strstr(status, "not-installed")) continue; entry->swName_len = snprintf( entry->swName, sizeof(entry->swName), "%s-%s", package, version); if (entry->swName_len >= sizeof(entry->swName)) entry->swName_len = sizeof(entry->swName)-1; entry->swType = (strcmp(essential, "yes") == 0) ? 2 /* operatingSystem */ : 4; /* application */ entry->swDate_len = 8; memcpy(entry->swDate, "\0\0\1\1\0\0\0\0", 8); } pclose(p); DEBUGMSGTL(("swinst:load:arch"," loaded %d entries\n", (int) CONTAINER_SIZE(container))); return 0; }
/** * load initial data * * TODO:350:M: Implement ipIfStatsTable data load * This function will also be called by the cache helper to load * the container again (after the container free function has been * called to free the previous contents). * * @param container container to which items should be inserted * * @retval MFD_SUCCESS : success. * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source * @retval MFD_ERROR : other error. * * This function is called to load the index(es) (and data, optionally) * for the every row in the data set. * * @remark * While loading the data, the only important thing is the indexes. * If access to your data is cheap/fast (e.g. you have a pointer to a * structure in memory), it would make sense to update the data here. * If, however, the accessing the data invovles more work (e.g. parsing * some other existing data, or peforming calculations to derive the data), * then you can limit yourself to setting the indexes and saving any * information you will need later. Then use the saved information in * ipIfStatsTable_row_prep() for populating data. * * @note * If you need consistency between rows (like you want statistics * for each row to be from the same time frame), you should set all * data here. * */ int ipIfStatsTable_container_load(netsnmp_container * container) { netsnmp_container *stats; DEBUGMSGTL(("verbose:ipIfStatsTable:ipIfStatsTable_container_load", "called\n")); netsnmp_assert(NULL != container); stats = netsnmp_access_systemstats_container_load(NULL, NETSNMP_ACCESS_SYSTEMSTATS_LOAD_IFTABLE); if (NULL == stats) return MFD_RESOURCE_UNAVAILABLE; /* msg already logged */ /* * TODO:351:M: |-> Load/update data in the ipIfStatsTable container. * loop over your ipIfStatsTable data, allocate a rowreq context, * set the index(es) [and data, optionally] and insert into * the container. */ /* * we just got a fresh copy of data. compare it to * what we've already got, and make any adjustements... */ CONTAINER_FOR_EACH(container, (netsnmp_container_obj_func *) _check_for_updates, stats); /* * now add any new entries */ CONTAINER_FOR_EACH(stats, (netsnmp_container_obj_func *) _add_new, container); /* * free the container. we've either claimed each ifentry, or released it, * so the dal function doesn't need to clear the container. */ netsnmp_access_systemstats_container_free(stats, NETSNMP_ACCESS_SYSTEMSTATS_FREE_DONT_CLEAR); DEBUGMSGT(("verbose:ipIfStatsTable:ipIfStatsTable_container_load", "%lu records\n", (unsigned long)CONTAINER_SIZE(container))); return MFD_SUCCESS; } /* ipIfStatsTable_container_load */
/* this is called after the connection on the server side by us to check other aspects about the connection and obtain the securityName from the remote certificate. */ int netsnmp_tlsbase_extract_security_name (SSL * ssl, _netsnmpTLSBaseData * tlsdata) { netsnmp_container *chain_maps; netsnmp_cert_map *cert_map, *peer_cert; netsnmp_iterator *itr; int rc; netsnmp_assert_or_return (ssl != NULL, SNMPERR_GENERR); netsnmp_assert_or_return (tlsdata != NULL, SNMPERR_GENERR); if (NULL == (chain_maps = netsnmp_openssl_get_cert_chain (ssl))) return SNMPERR_GENERR; /* * map fingerprints to mapping entries */ rc = netsnmp_cert_get_secname_maps (chain_maps); if ((-1 == rc) || (CONTAINER_SIZE (chain_maps) == 0)) { netsnmp_cert_map_container_free (chain_maps); return SNMPERR_GENERR; } /* * change container to sorted (by clearing unsorted option), then * iterate over it until we find a map that returns a secname. */ CONTAINER_SET_OPTIONS (chain_maps, 0, rc); itr = CONTAINER_ITERATOR (chain_maps); if (NULL == itr) { snmp_log (LOG_ERR, "could not get iterator for secname fingerprints\n"); netsnmp_cert_map_container_free (chain_maps); return SNMPERR_GENERR; } peer_cert = cert_map = ITERATOR_FIRST (itr); for (; !tlsdata->securityName && cert_map; cert_map = ITERATOR_NEXT (itr)) tlsdata->securityName = netsnmp_openssl_extract_secname (cert_map, peer_cert); ITERATOR_RELEASE (itr); netsnmp_cert_map_container_free (chain_maps); return (tlsdata->securityName ? SNMPERR_SUCCESS : SNMPERR_GENERR); }
/* * sql trap handler */ int mysql_handler(netsnmp_pdu *pdu, netsnmp_transport *transport, netsnmp_trapd_handler *handler) { sql_buf *sqlb; int old_format, rc; DEBUGMSGTL(("sql:handler", "called\n")); /** allocate a buffer to save data */ sqlb = _sql_buf_get(); if (NULL == sqlb) { snmp_log(LOG_ERR, "Could not allocate trap sql buffer\n"); return syslog_handler( pdu, transport, handler ); } /** save OID output format and change to numeric */ old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC); rc = _sql_save_trap_info(sqlb, pdu, transport); rc = _sql_save_varbind_info(sqlb, pdu); /** restore previous OID output format */ netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, old_format); /** insert into queue */ rc = CONTAINER_INSERT(_sql.queue, sqlb); if(rc) { snmp_log(LOG_ERR, "Could not log queue sql trap buffer\n"); _sql_log(sqlb, NULL); _sql_buf_free(sqlb, 0); return -1; } /** save queue if size is > max */ if (CONTAINER_SIZE(_sql.queue) >= _sql.queue_max) _sql_process_queue(0,NULL); return 0; }
int delete_rdr_row (SaHpiDomainIdT domain_id, SaHpiResourceIdT resource_id, SaHpiEntryIdT num, SaHpiRdrTypeT type) { saHpiRdrTable_context *ctx; oid rdr_oid[RDR_INDEX_NR]; netsnmp_index rdr_index; int rc = AGENT_ERR_NOT_FOUND; DEBUGMSGTL ((AGENT, "delete_rdr_row (%d, %d, %d, %d). Entry.\n", domain_id, resource_id, num, type)); // Look at the MIB to find out what the indexs are rdr_oid[0] = domain_id; rdr_oid[1] = resource_id; rdr_oid[2] = num; rdr_oid[3] = type; // Possible more indexs? rdr_index.oids = (oid *) & rdr_oid; rdr_index.len = RDR_INDEX_NR; ctx = CONTAINER_FIND (cb.container, &rdr_index); if (ctx) { CONTAINER_REMOVE (cb.container, ctx); saHpiRdrTable_delete_row (ctx); rdr_count = CONTAINER_SIZE (cb.container); rc = AGENT_ERR_NOERROR; } DEBUGMSGTL ((AGENT, "delete_rdr_row. Exit (rc: %d)\n", rc)); return rc; }
int ipv4InterfaceTable_container_size(void) { return CONTAINER_SIZE(ipv4InterfaceTable_if_ctx.container); }
SaErrorT populate_saHpiDomainEventTable(SaHpiSessionIdT sessionid, SaHpiEventT *event, oid * this_child_oid, size_t *this_child_oid_len) { SaErrorT rv = SA_OK; int new_row = MIB_FALSE; oid domain_evt_oid[DOMAIN_EVENT_INDEX_NR]; netsnmp_index domain_evt_idx; saHpiDomainEventTable_context *domain_evt_ctx; oid column[2]; int column_len = 2; DR_XREF *dr_entry; SaHpiDomainIdResourceIdArrayT dr_pair; DEBUGMSGTL ((AGENT, "populate_saHpiDomainEventTable, called\n")); /* check for NULL pointers */ if (!event) { DEBUGMSGTL ((AGENT, "ERROR: populate_saHpiDomainEventTable() passed NULL event pointer\n")); return AGENT_ERR_INTERNAL_ERROR; } /* BUILD oid for new row */ /* assign the number of indices */ domain_evt_idx.len = DOMAIN_EVENT_INDEX_NR; /** Index saHpiDomainId is external */ domain_evt_oid[0] = get_domain_id(sessionid); /** Index saHpiDomainEventEntryId is internal */ dr_pair.domainId_resourceId_arry[0] = get_domain_id(sessionid); dr_pair.domainId_resourceId_arry[1] = event->Source; dr_entry = domain_resource_pair_get(&dr_pair, &dr_table); if (dr_entry == NULL) { DEBUGMSGTL ((AGENT, "ERROR: populate_saHpiDomainEventTable() domain_resource_pair_get returned NULL\n")); return AGENT_ERR_INTERNAL_ERROR; } domain_evt_oid[1] = dr_entry->entry_id++; /** Index saHpiEventSeverity is external */ domain_evt_oid[2] = event->Severity + 1; /* assign the indices to the index */ domain_evt_idx.oids = (oid *) & domain_evt_oid; /* See if Row exists. */ domain_evt_ctx = NULL; domain_evt_ctx = CONTAINER_FIND(cb.container, &domain_evt_idx); if (!domain_evt_ctx) { // New entry. Add it domain_evt_ctx = saHpiDomainEventTable_create_row(&domain_evt_idx); new_row = MIB_TRUE; } if (!domain_evt_ctx) { snmp_log (LOG_ERR, "Not enough memory for a Domain Event row!"); rv = AGENT_ERR_INTERNAL_ERROR; } /** SaHpiEntryId = ASN_UNSIGNED */ domain_evt_ctx->saHpiDomainEventEntryId = domain_evt_oid[2]; /** SaHpiTime = ASN_COUNTER64 */ assign_timestamp(&event->Timestamp, &domain_evt_ctx->saHpiDomainEventTimestamp); /** INTEGER = ASN_INTEGER */ domain_evt_ctx->saHpiDomainEventType = event->EventDataUnion.DomainEvent.Type + 1; if (new_row == MIB_TRUE) CONTAINER_INSERT (cb.container, domain_evt_ctx); domain_event_entry_count = CONTAINER_SIZE (cb.container); /* create full oid on This row for parent RowPointer */ column[0] = 1; column[1] = COLUMN_SAHPIDOMAINEVENTTIMESTAMP; memset(this_child_oid, 0, sizeof(this_child_oid)); build_full_oid(saHpiDomainEventTable_oid, saHpiDomainEventTable_oid_len, column, column_len, &domain_evt_idx, this_child_oid, MAX_OID_LEN, this_child_oid_len); return SA_OK; }
/** * * @retval 0 no errors * @retval !0 errors */ static int _load6(netsnmp_container *container, u_int load_flags) { int rc = 0; FILE *in; char line[180]; static int log_open_err = 1; netsnmp_assert(NULL != container); #undef PROCFILE #define PROCFILE "/proc/net/tcp6" if (!(in = fopen(PROCFILE, "r"))) { snmp_log(LOG_ERR,"could not open " PROCFILE "\n"); if (1 == log_open_err) { snmp_log(LOG_ERR,"could not open " PROCFILE "\n"); log_open_err = 0; } return -2; } /* * if we turned off logging of open errors, turn it back on now that * we have been able to open the file. */ if (0 == log_open_err) log_open_err = 1; fgets(line, sizeof(line), in); /* skip header */ /* * Note: PPC (big endian) * * sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode * 0: 00000000000000000000000000000001:1466 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 500 0 326699 1 efb81580 3000 0 0 2 -1 */ while (fgets(line, sizeof(line), in)) { netsnmp_tcpconn_entry *entry; int state, rc, local_port, remote_port, tmp_state; unsigned long long inode; size_t buf_len, offset; char local_addr[48], remote_addr[48]; u_char *tmp_ptr; if (6 != (rc = sscanf(line, "%*d: %47[0-9A-Z]:%x %47[0-9A-Z]:%x %x %*x:%*x %*x:%*x %*x %*x %*x %llu", local_addr, &local_port, remote_addr, &remote_port, &tmp_state, &inode))) { DEBUGMSGT(("access:tcpconn:container", "error parsing line (%d != 6)\n", rc)); DEBUGMSGT(("access:tcpconn:container"," line '%s'\n", line)); continue; } DEBUGMSGT(("verbose:access:tcpconn:container"," line '%s'\n", line)); /* * check if we care about listen state */ state = (tmp_state & 0xf) < 12 ? linux_states[tmp_state & 0xf] : 2; if (load_flags) { if (TCPCONNECTIONSTATE_LISTEN == state) { if (load_flags & NETSNMP_ACCESS_TCPCONN_LOAD_NOLISTEN) { DEBUGMSGT(("verbose:access:tcpconn:container", " skipping listen\n")); continue; } } else if (load_flags & NETSNMP_ACCESS_TCPCONN_LOAD_ONLYLISTEN) { DEBUGMSGT(("verbose:access:tcpconn:container", " skipping non-listen\n")); continue; } } /* */ entry = netsnmp_access_tcpconn_entry_create(); if(NULL == entry) { rc = -3; break; } /** oddly enough, these appear to already be in network order */ entry->loc_port = (unsigned short) local_port; entry->rmt_port = (unsigned short) remote_port; entry->tcpConnState = state; entry->pid = netsnmp_get_pid_from_inode(inode); /** the addr string may need work */ buf_len = strlen(local_addr); if ((32 != buf_len) || (-1 == netsnmp_addrstr_hton(local_addr, 32))) { DEBUGMSGT(("verbose:access:tcpconn:container", " error processing local address\n")); netsnmp_access_tcpconn_entry_free(entry); continue; } offset = 0; tmp_ptr = entry->loc_addr; rc = netsnmp_hex_to_binary(&tmp_ptr, &buf_len, &offset, 0, local_addr, NULL); entry->loc_addr_len = offset; if (( 16 != entry->loc_addr_len ) && ( 20 != entry->loc_addr_len )) { DEBUGMSGT(("access:tcpconn:container", "error parsing local addr (%d != 16|20)\n", entry->loc_addr_len)); DEBUGMSGT(("access:tcpconn:container"," line '%s'\n", line)); netsnmp_access_tcpconn_entry_free(entry); continue; } buf_len = strlen((char*)remote_addr); if ((32 != buf_len) || (-1 == netsnmp_addrstr_hton(remote_addr, 32))) { DEBUGMSGT(("verbose:access:tcpconn:container", " error processing remote address\n")); netsnmp_access_tcpconn_entry_free(entry); continue; } offset = 0; tmp_ptr = entry->rmt_addr; rc = netsnmp_hex_to_binary(&tmp_ptr, &buf_len, &offset, 0, remote_addr, NULL); entry->rmt_addr_len = offset; if (( 16 != entry->rmt_addr_len ) && ( 20 != entry->rmt_addr_len )) { DEBUGMSGT(("access:tcpconn:container", "error parsing remote addr (%d != 16|20)\n", entry->rmt_addr_len)); DEBUGMSGT(("access:tcpconn:container"," line '%s'\n", line)); netsnmp_access_tcpconn_entry_free(entry); continue; } /* * add entry to container */ entry->arbitrary_index = CONTAINER_SIZE(container) + 1; CONTAINER_INSERT(container, entry); } fclose(in); if(rc<0) return rc; return 0; }
/* --------------------------------------------------------------------- */ int netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags) { DIR *procdir = NULL; struct dirent *procentry_p; FILE *fp; int pid, rc, i; char buf[BUFSIZ], buf2[BUFSIZ], *cp; netsnmp_swrun_entry *entry; procdir = opendir("/proc"); if ( NULL == procdir ) { snmp_log( LOG_ERR, "Failed to open /proc" ); return -1; } /* * Walk through the list of processes in the /proc tree */ while ( NULL != (procentry_p = readdir( procdir ))) { pid = atoi( procentry_p->d_name ); if ( 0 == pid ) continue; /* Presumably '.' or '..' */ entry = netsnmp_swrun_entry_create(pid); if (NULL == entry) continue; /* error already logged by function */ rc = CONTAINER_INSERT(container, entry); /* * Now extract the interesting information * from the various /proc{PID}/ interface files */ /* * Name: process name */ snprintf( buf2, BUFSIZ, "/proc/%d/status", pid ); fp = fopen( buf2, "r" ); memset(buf, 0, sizeof(buf)); fgets( buf, BUFSIZ-1, fp ); fclose(fp); for ( cp = buf; *cp != ':'; cp++ ) ; while (isspace(*(++cp))) /* Skip ':' and following spaces */ ; entry->hrSWRunName_len = snprintf(entry->hrSWRunName, sizeof(entry->hrSWRunName)-1, "%s", cp); if ( '\n' == entry->hrSWRunName[ entry->hrSWRunName_len-1 ]) { entry->hrSWRunName[ entry->hrSWRunName_len-1 ] = '\0'; entry->hrSWRunName_len--; /* Stamp on trailing newline */ } /* * Command Line: * argv[0] '\0' argv[1] '\0' .... */ snprintf( buf2, BUFSIZ, "/proc/%d/cmdline", pid ); fp = fopen( buf2, "r" ); memset(buf, 0, sizeof(buf)); cp = fgets( buf, BUFSIZ-1, fp ); fclose(fp); if ( cp ) { /* * argv[0] is hrSWRunPath */ entry->hrSWRunPath_len = snprintf(entry->hrSWRunPath, sizeof(entry->hrSWRunPath)-1, "%s", buf); /* * Stitch together argv[1..] to construct hrSWRunParameters */ cp = buf + entry->hrSWRunPath_len+1; while ( 1 ) { while (*cp) cp++; if ( '\0' == *(cp+1)) break; /* '\0''\0' => End of command line */ *cp = ' '; } entry->hrSWRunParameters_len = snprintf(entry->hrSWRunParameters, sizeof(entry->hrSWRunParameters)-1, "%s", buf + entry->hrSWRunPath_len+1); } else { memcpy(entry->hrSWRunPath, entry->hrSWRunName, entry->hrSWRunName_len); entry->hrSWRunPath_len = entry->hrSWRunName_len; entry->hrSWRunParameters_len = 0; } /* * XXX - No information regarding system processes vs applications */ entry->hrSWRunType = HRSWRUNTYPE_APPLICATION; /* * {xxx} {xxx} STATUS {xxx}*10 UTIME STIME {xxx}*8 RSS */ snprintf( buf, BUFSIZ, "/proc/%d/stat", pid ); fp = fopen( buf, "r" ); fgets( buf, BUFSIZ-1, fp ); fclose(fp); cp = buf; while ( ' ' != *(cp++)) /* Skip first field */ ; while ( ' ' != *(cp++)) /* Skip second field */ ; switch (*cp) { case 'R': entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING; break; case 'S': entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE; break; case 'D': case 'T': entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE; break; case 'Z': default: entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID; break; } for (i=10; i; i--) { /* Skip STATUS + 10 fields */ while (' ' != *(cp++)) ; cp++; } entry->hrSWRunPerfCPU = atoi( cp ); /* utime */ while ( ' ' != *(cp++)) ; cp++; /* Skip utime */ entry->hrSWRunPerfCPU += atoi( cp ); /* +stime */ for (i=8; i; i--) { /* Skip stime + 8 fields */ while (' ' != *(cp++)) ; cp++; } entry->hrSWRunPerfMem = atoi( cp ); /* rss */ entry->hrSWRunPerfMem *= (getpagesize()/1024); /* in kB */ } closedir( procdir ); DEBUGMSGTL(("swrun:load:arch"," loaded %d entries\n", CONTAINER_SIZE(container))); return 0; }
int swrun_count_processes( void ) { netsnmp_cache_check_and_reload(swrun_cache); return ( swrun_container ? CONTAINER_SIZE(swrun_container) : 0 ); }
/** * load initial data * * TODO:350:M: Implement ipAddressTable data load * This function will also be called by the cache helper to load * the container again (after the container free function has been * called to free the previous contents). * * @param container container to which items should be inserted * * @retval MFD_SUCCESS : success. * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source * @retval MFD_ERROR : other error. * * This function is called to load the index(es) (and data, optionally) * for the every row in the data set. * * @remark * While loading the data, the only important thing is the indexes. * If access to your data is cheap/fast (e.g. you have a pointer to a * structure in memory), it would make sense to update the data here. * If, however, the accessing the data invovles more work (e.g. parsing * some other existing data, or peforming calculations to derive the data), * then you can limit yourself to setting the indexes and saving any * information you will need later. Then use the saved information in * ipAddressTable_row_prep() for populating data. * * @note * If you need consistency between rows (like you want statistics * for each row to be from the same time frame), you should set all * data here. * */ int ipAddressTable_container_load(netsnmp_container *container) { netsnmp_container *ipaddress_container; void *tmp_ptr[2]; DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_cache_load", "called\n")); /* * TODO:351:M: |-> Load/update data in the ipAddressTable container. * loop over your ipAddressTable data, allocate a rowreq context, * set the index(es) [and data, optionally] and insert into * the container. */ ipaddress_container = netsnmp_access_ipaddress_container_load(NULL, NETSNMP_ACCESS_IPADDRESS_LOAD_ADDL_IDX_BY_ADDR); /* * we just got a fresh copy of interface data. compare it to * what we've already got, and make any adjustments, saving * missing addresses to be deleted. */ tmp_ptr[0] = ipaddress_container->next; tmp_ptr[1] = NULL; CONTAINER_FOR_EACH(container, (netsnmp_container_obj_func *) _check_entry_for_updates, tmp_ptr); /* * now add any new interfaces */ CONTAINER_FOR_EACH(ipaddress_container, (netsnmp_container_obj_func *) _add_new_entry, container); /* * free the container. we've either claimed each entry, or released it, * so the access function doesn't need to clear the container. */ netsnmp_access_ipaddress_container_free(ipaddress_container, NETSNMP_ACCESS_IPADDRESS_FREE_DONT_CLEAR); /* * remove deleted addresses from table container */ if (NULL != tmp_ptr[1]) { netsnmp_container *tmp_container = (netsnmp_container *) tmp_ptr[1]; ipAddressTable_rowreq_ctx *tmp_ctx; /* * this works because the tmp_container is a linked list, * which can be used like a stack... */ while (CONTAINER_SIZE(tmp_container)) { /* * get from delete list */ tmp_ctx = (ipAddressTable_rowreq_ctx*)CONTAINER_FIRST(tmp_container); /* * release context, delete from table container */ CONTAINER_REMOVE(container, tmp_ctx); ipAddressTable_release_rowreq_ctx(tmp_ctx); /* * pop off delete list */ CONTAINER_REMOVE(tmp_container, NULL); } } DEBUGMSGT(("verbose:ipAddressTable:ipAddressTable_cache_load", "%lu records\n", (unsigned long)CONTAINER_SIZE(container))); return MFD_SUCCESS; }
/* --------------------------------------------------------------------- */ int netsnmp_swinst_arch_load( netsnmp_container *container, u_int flags) { rpmts ts; rpmdbMatchIterator mi; Header h; char *n, *v, *r, *g; int32_t *t; time_t install_time; size_t date_len; int i = 1; netsnmp_swinst_entry *entry; ts = rpmtsCreate(); rpmtsSetVSFlags( ts, (_RPMVSF_NOSIGNATURES|_RPMVSF_NODIGESTS)); mi = rpmtsInitIterator( ts, RPMDBI_PACKAGES, NULL, 0); if (mi == NULL) NETSNMP_LOGONCE((LOG_ERR, "rpmdbOpen() failed\n")); while (NULL != (h = rpmdbNextIterator( mi ))) { const u_char *dt; entry = netsnmp_swinst_entry_create( i++ ); if (NULL == entry) continue; /* error already logged by function */ CONTAINER_INSERT(container, entry); h = headerLink( h ); headerGetEntry( h, RPMTAG_NAME, NULL, (void**)&n, NULL); headerGetEntry( h, RPMTAG_VERSION, NULL, (void**)&v, NULL); headerGetEntry( h, RPMTAG_RELEASE, NULL, (void**)&r, NULL); headerGetEntry( h, RPMTAG_GROUP, NULL, (void**)&g, NULL); headerGetEntry( h, RPMTAG_INSTALLTIME, NULL, (void**)&t, NULL); entry->swName_len = snprintf( entry->swName, sizeof(entry->swName), "%s-%s-%s", n, v, r); if (entry->swName_len > sizeof(entry->swName)) entry->swName_len = sizeof(entry->swName); entry->swType = (NULL != strstr( g, "System Environment")) ? 2 /* operatingSystem */ : 4; /* application */ install_time = *t; dt = date_n_time( &install_time, &date_len ); if (date_len != 8 && date_len != 11) { snmp_log(LOG_ERR, "Bogus length from date_n_time for %s", entry->swName); entry->swDate_len = 0; } else { entry->swDate_len = date_len; memcpy(entry->swDate, dt, entry->swDate_len); } headerFree( h ); } rpmdbFreeIterator( mi ); rpmtsFree( ts ); DEBUGMSGTL(("swinst:load:arch", "loaded %d entries\n", (int)CONTAINER_SIZE(container))); return 0; }