/* * This function was created to differentiate actions * that are appropriate for Linux 2.4 kernels, but not later kernels. * * This function can be used to test kernels on any platform that supports uname(). * * If not running a platform that supports uname(), return -1. * * If ospname matches, and the release matches up through the prefix, * return 0. * If the release is ordered higher, return 1. * Be aware that "ordered higher" is not a guarantee of correctness. */ int netsnmp_os_prematch(const char *ospmname, const char *ospmrelprefix) { #if HAVE_SYS_UTSNAME_H static int printOSonce = 1; struct utsname utsbuf; if ( 0 != uname(&utsbuf)) return -1; if (printOSonce) { printOSonce = 0; /* show the four elements that the kernel can be sure of */ DEBUGMSGT(("daemonize","sysname '%s',\nrelease '%s',\nversion '%s',\nmachine '%s'\n", utsbuf.sysname, utsbuf.release, utsbuf.version, utsbuf.machine)); } if (0 != strcasecmp(utsbuf.sysname, ospmname)) return -1; /* Required to match only the leading characters */ return strncasecmp(utsbuf.release, ospmrelprefix, strlen(ospmrelprefix)); #else return -1; #endif /* HAVE_SYS_UTSNAME_H */ }
/** * check validity of ipAddressAddrType index portion * * @retval MFD_SUCCESS : the incoming value is legal * @retval MFD_ERROR : the incoming value is NOT legal * * @note this is not the place to do any checks for the sanity * of multiple indexes. Those types of checks should be done in the * ipAddressTable_validate_index() function. * * @note Also keep in mind that if the index refers to a row in this or * some other table, you can't check for that row here to make * decisions, since that row might not be created yet, but may * be created during the processing this request. If you have * such checks, they should be done in the check_dependencies * function, because any new/deleted/changed rows should be * available then. * * The following checks have already been done for you: * The value is one of unknown(0), ipv4(1), ipv6(2), ipv4z(3), ipv6z(4), dns(16) * * If there a no other checks you need to do, simply return MFD_SUCCESS. */ int ipAddressAddrType_check_index(ipAddressTable_rowreq_ctx * rowreq_ctx) { DEBUGMSGTL(("verbose:ipAddressTable:ipAddressAddrType_check_index", "called\n")); netsnmp_assert(NULL != rowreq_ctx); /* * TODO:426:M: |-> Check ipAddressTable index ipAddressAddrType. * check that index value in the table context is legal. * (rowreq_ctx->tbl_index.ipAddressAddrType) */ switch (rowreq_ctx->tbl_idx.ipAddressAddrType) { case INETADDRESSTYPE_IPV4: case INETADDRESSTYPE_IPV6: break; default: DEBUGMSGT(("ipAddressTable", "illegal addr type\n")); return MFD_ERROR; } return MFD_SUCCESS; /* ipAddressAddrType index ok */ } /* ipAddressAddrType_check_index */
netsnmp_ipaddress_entry * netsnmp_access_ipaddress_entry_create(void) { netsnmp_ipaddress_entry *entry = SNMP_MALLOC_TYPEDEF(netsnmp_ipaddress_entry); int rc = 0; entry->oid_index.len = 1; entry->oid_index.oids = &entry->ns_ia_index; /* * set up defaults */ entry->ia_type = IPADDRESSTYPE_UNICAST; entry->ia_status = IPADDRESSSTATUSTC_PREFERRED; entry->ia_storagetype = STORAGETYPE_VOLATILE; rc = netsnmp_arch_ipaddress_entry_init(entry); if (SNMP_ERR_NOERROR != rc) { DEBUGMSGT(("access:ipaddress:create","error %d in arch init\n")); netsnmp_access_ipaddress_entry_free(entry); } return entry; }
/* * delete an entry */ int netsnmp_arch_ipaddress_delete (netsnmp_ipaddress_entry * entry) { if (NULL == entry) return -1; DEBUGMSGT (("access:ipaddress:create", "not applicable\n")); 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 void * _iterator_find_next(iterator_info *ii, const void *data) { DEBUGMSGT(("container_iterator",">%s\n", "_iterator_find_next")); if(NULL == ii) return NULL; return _iterator_get_next(ii, data); }
/** callback function to call cache load function */ static void _timer_reload(unsigned int regNo, void *clientargs) { netsnmp_cache *cache = (netsnmp_cache *)clientargs; DEBUGMSGT(("cache_timer:start", "loading cache %p\n", cache)); cache->expired = 1; _cache_load(cache); }
/** * open file and get stats */ netsnmp_file * netsnmp_file_new(const char *name, int fs_flags, mode_t mode, u_int ns_flags) { netsnmp_file *filei = netsnmp_file_fill(NULL, name, fs_flags, mode, 0); if (NULL == filei) return NULL; if (ns_flags & NETSNMP_FILE_STATS) { filei->stats = (struct stat*)calloc(1, sizeof(*(filei->stats))); if (NULL == filei->stats) DEBUGMSGT(("nsfile:new", "no memory for stats\n")); else if (stat(name, filei->stats) != 0) DEBUGMSGT(("nsfile:new", "error getting stats\n")); } if (ns_flags & NETSNMP_FILE_AUTO_OPEN) netsnmp_file_open(filei); return filei; }
/********************************************************************** * * container * **********************************************************************/ static void _iterator_free(iterator_info *ii) { DEBUGMSGT(("container_iterator",">%s\n", "_iterator_free")); if(NULL == ii) return; if(ii->user_ctx) ii->free_user_ctx(ii->user_ctx,ii->user_ctx); free(ii); }
static int _iterator_release(iterator_info *ii, const void *data) { DEBUGMSGT(("container_iterator",">%s\n", "_iterator_release")); if(NULL == ii) return -1; if(NULL == ii->release_data) return -1; return ii->release_data(ii->user_ctx, data); }
/* * create a new entry */ int netsnmp_arch_route_delete(netsnmp_route_entry *entry) { if (NULL == entry) return -1; if (4 != entry->rt_dest_len) { DEBUGMSGT(("access:route:create", "only ipv4 supported\n")); return -2; } return _netsnmp_ioctl_route_delete_v4(entry); }
/* * create a new entry */ int netsnmp_arch_ipaddress_create(netsnmp_ipaddress_entry *entry) { if (NULL == entry) return -1; if (4 != entry->ia_address_len) { DEBUGMSGT(("access:ipaddress:create", "only ipv4 supported\n")); return -2; } return _netsnmp_ioctl_ipaddress_set_v4(entry); }
/** * 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 int _cache_load( netsnmp_cache *cache ) { int ret = -1; /* * If we've got a valid cache, then release it before reloading */ if (cache->valid && (! (cache->flags & NETSNMP_CACHE_DONT_FREE_BEFORE_LOAD))) _cache_free(cache); if ( cache->load_cache) ret = cache->load_cache(cache, cache->magic); if (ret < 0) { DEBUGMSGT(("helper:cache_handler", " load failed (%d)\n", ret)); cache->valid = 0; return ret; } cache->valid = 1; cache->expired = 0; /* * If we didn't previously have any valid caches outstanding, * then schedule a pass of the auto-release routine. */ if ((!cache_outstanding_valid) && (! (cache->flags & NETSNMP_CACHE_DONT_FREE_EXPIRED))) { snmp_alarm_register(CACHE_RELEASE_FREQUENCY, 0, release_cached_resources, NULL); cache_outstanding_valid = 1; } netsnmp_set_monotonic_marker(&cache->timestampM); DEBUGMSGT(("helper:cache_handler", " loaded (%d)\n", cache->timeout)); return ret; }
/* * 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); }
int netsnmp_tlsbase_config (struct netsnmp_transport_s *t, const char *token, const char *value) { _netsnmpTLSBaseData *tlsdata; netsnmp_assert_or_return (t != NULL, -1); netsnmp_assert_or_return (t->data != NULL, -1); tlsdata = t->data; if ((strcmp (token, "localCert") == 0) || (strcmp (token, "our_identity") == 0)) { SNMP_FREE (tlsdata->our_identity); tlsdata->our_identity = strdup (value); DEBUGMSGT (("tls:config", "our identity %s\n", value)); } if ((strcmp (token, "peerCert") == 0) || (strcmp (token, "their_identity") == 0)) { SNMP_FREE (tlsdata->their_identity); tlsdata->their_identity = strdup (value); DEBUGMSGT (("tls:config", "their identity %s\n", value)); } if ((strcmp (token, "peerHostname") == 0) || (strcmp (token, "their_hostname") == 0)) { SNMP_FREE (tlsdata->their_hostname); tlsdata->their_hostname = strdup (value); } if ((strcmp (token, "trust_cert") == 0) || (strcmp (token, "trustCert") == 0)) { SNMP_FREE (tlsdata->trust_cert); tlsdata->trust_cert = strdup (value); } return SNMPERR_SUCCESS; }
/** * check validity of ipAddressAddr index portion * * @retval MFD_SUCCESS : the incoming value is legal * @retval MFD_ERROR : the incoming value is NOT legal * * @note this is not the place to do any checks for the sanity * of multiple indexes. Those types of checks should be done in the * ipAddressTable_validate_index() function. * * @note Also keep in mind that if the index refers to a row in this or * some other table, you can't check for that row here to make * decisions, since that row might not be created yet, but may * be created during the processing this request. If you have * such checks, they should be done in the check_dependencies * function, because any new/deleted/changed rows should be * available then. * * The following checks have already been done for you: * The length is in (one of) the range set(s): 0 - 255 * * If there a no other checks you need to do, simply return MFD_SUCCESS. */ int ipAddressAddr_check_index(ipAddressTable_rowreq_ctx * rowreq_ctx) { DEBUGMSGTL(("verbose:ipAddressTable:ipAddressAddr_check_index", "called\n")); netsnmp_assert(NULL != rowreq_ctx); /* * TODO:426:M: |-> Check ipAddressTable index ipAddressAddr. * check that index value in the table context is legal. * (rowreq_ctx->tbl_index.ipAddressAddr) */ switch (rowreq_ctx->tbl_idx.ipAddressAddrType) { case INETADDRESSTYPE_IPV4: if (4 != rowreq_ctx->tbl_idx.ipAddressAddr_len) { DEBUGMSGT(("ipAddressTable", "bad addr len\n")); return MFD_ERROR; } break; case INETADDRESSTYPE_IPV6: /** xxx-rks: allow 20? */ if (16 != rowreq_ctx->tbl_idx.ipAddressAddr_len) { DEBUGMSGT(("ipAddressTable", "bad addr len\n")); return MFD_ERROR; } break; default: return MFD_ERROR; } return MFD_SUCCESS; /* ipAddressAddr index ok */ } /* ipAddressAddr_check_index */
/* * create a new entry */ int netsnmp_arch_ipaddress_delete(netsnmp_ipaddress_entry *entry) { if (NULL == entry) return -1; if (4 == entry->ia_address_len) { return -2; } else if (16 == entry->ia_address_len) { return -3; } else { DEBUGMSGT(("access:ipaddress:create", "only ipv4 supported\n")); return -2; } }
/* * create a new entry */ int netsnmp_arch_ipaddress_create(netsnmp_ipaddress_entry *entry) { if (NULL == entry) return -1; if (4 == entry->ia_address_len) { return -1; } else if (16 == entry->ia_address_len) { return -1; } else { DEBUGMSGT(("access:ipaddress:create", "wrong length of IP address\n")); return -2; } }
/** * 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 */
/********************************************************************** * * iterator * **********************************************************************/ static void * _iterator_get(iterator_info *ii, const void *key) { int cmp, rc = SNMP_ERR_NOERROR; netsnmp_ref_void best = { NULL }; netsnmp_ref_void tmp = { NULL }; netsnmp_ref_void loop_ctx = { NULL }; DEBUGMSGT(("container_iterator",">%s\n", "_iterator_get")); if(ii->init_loop_ctx) ii->init_loop_ctx(ii->user_ctx, &loop_ctx); rc = ii->get_first(ii->user_ctx, &loop_ctx, &tmp); if(SNMP_ERR_NOERROR != rc) { if(SNMP_ENDOFMIBVIEW != rc) snmp_log(LOG_ERR, "bad rc %d from get_next\n", rc); } else { for( ; (NULL != tmp.val) && (SNMP_ERR_NOERROR == rc); rc = ii->get_next(ii->user_ctx, &loop_ctx, &tmp) ) { /* * if keys are equal, we are done. */ cmp = ii->c.compare(tmp.val, key); if(0 == cmp) { best.val = tmp.val; if(ii->get_data) ii->get_data(ii->user_ctx, &loop_ctx, &best); } /* * if data is sorted and if key is greater, * we are done (not found) */ if((cmp > 0) && ii->sorted) break; } /* end for */ } if(ii->cleanup_loop_ctx) ii->cleanup_loop_ctx(ii->user_ctx,&loop_ctx); return best.val; }
/** * @internal * wrapper */ static ipv6ScopeZoneIndexTable_rowreq_ctx * _mfd_ipv6ScopeZoneIndexTable_rowreq_from_index(netsnmp_index * oid_idx, int *rc_ptr) { ipv6ScopeZoneIndexTable_rowreq_ctx *rowreq_ctx; ipv6ScopeZoneIndexTable_mib_index mib_idx; int rc; DEBUGMSGTL(("internal:ipv6ScopeZoneIndexTable:_mfd_ipv6ScopeZoneIndexTable_rowreq_from_index", "called\n")); if (NULL == rc_ptr) rc_ptr = &rc; *rc_ptr = MFD_SUCCESS; memset(&mib_idx, 0x0, sizeof(mib_idx)); /* * try to parse oid */ *rc_ptr = ipv6ScopeZoneIndexTable_index_from_oid(oid_idx, &mib_idx); if (MFD_SUCCESS != *rc_ptr) { DEBUGMSGT(("ipv6ScopeZoneIndexTable", "error parsing index\n")); return NULL; } /* * allocate new context */ rowreq_ctx = ipv6ScopeZoneIndexTable_allocate_rowreq_ctx(NULL, NULL); if (NULL == rowreq_ctx) { *rc_ptr = MFD_ERROR; return NULL; /* msg already logged */ } memcpy(&rowreq_ctx->tbl_idx, &mib_idx, sizeof(mib_idx)); /* * copy indexes */ rowreq_ctx->oid_idx.len = oid_idx->len; memcpy(rowreq_ctx->oid_idx.oids, oid_idx->oids, oid_idx->len * sizeof(oid)); return rowreq_ctx; } /* _mfd_ipv6ScopeZoneIndexTable_rowreq_from_index */
/** stops the recurring cache_load callback */ void netsnmp_cache_timer_stop(netsnmp_cache *cache) { if(NULL == cache) return; if(0 == cache->timer_id) { snmp_log(LOG_WARNING, "cache has no timer id.\n"); return; } DEBUGMSGT(("cache_timer:stop", "stopping timer %lu for cache %p\n", cache->timer_id, cache)); snmp_alarm_unregister(cache->timer_id); cache->flags |= NETSNMP_CACHE_AUTO_RELOAD; }
/** * check entry for update */ static void _snarf_route_entry(netsnmp_route_entry *route_entry, netsnmp_container *container) { inetCidrRouteTable_rowreq_ctx *rowreq_ctx; netsnmp_assert(NULL != route_entry); netsnmp_assert(NULL != container); /* * per inetCidrRouteType: * * Routes which do not result in traffic forwarding or * rejection should not be displayed even if the * implementation keeps them stored internally. */ if (route_entry->rt_type == 0) { /* set when route not up */ DEBUGMSGT(("verbose:inetCidrRouteTable:inetCidrRouteTable_cache_load", "skipping route\n")); netsnmp_access_route_entry_free(route_entry); return; } /* * allocate an row context and set the index(es), then add it to * the container */ rowreq_ctx = inetCidrRouteTable_allocate_rowreq_ctx(route_entry, NULL); if ((NULL != rowreq_ctx) && (MFD_SUCCESS == inetCidrRouteTable_indexes_set (rowreq_ctx, route_entry->rt_dest_type, (char *) route_entry->rt_dest, route_entry->rt_dest_len, route_entry->rt_pfx_len, route_entry->rt_policy, route_entry->rt_policy_len, route_entry->rt_nexthop_type, (char *) route_entry->rt_nexthop, route_entry->rt_nexthop_len))) { CONTAINER_INSERT(container, rowreq_ctx); rowreq_ctx->row_status = ROWSTATUS_ACTIVE; } else { if (rowreq_ctx) { snmp_log(LOG_ERR, "error setting index while loading " "inetCidrRoute cache.\n"); inetCidrRouteTable_release_rowreq_ctx(rowreq_ctx); } else netsnmp_access_route_entry_free(route_entry); } }
netsnmp_log_handler * netsnmp_register_loghandler( int type, int priority ) { netsnmp_log_handler *logh; logh = SNMP_MALLOC_TYPEDEF(netsnmp_log_handler); if (!logh) return NULL; DEBUGMSGT(("logging:register", "registering log type %d with pri %d\n", type, priority)); logh->type = type; switch ( type ) { case NETSNMP_LOGHANDLER_STDOUT: logh->imagic = 1; /* fallthrough */ case NETSNMP_LOGHANDLER_STDERR: logh->handler = log_handler_stdouterr; break; case NETSNMP_LOGHANDLER_FILE: logh->handler = log_handler_file; logh->imagic = 1; break; case NETSNMP_LOGHANDLER_SYSLOG: logh->handler = log_handler_syslog; break; case NETSNMP_LOGHANDLER_CALLBACK: logh->handler = log_handler_callback; break; case NETSNMP_LOGHANDLER_NONE: logh->handler = log_handler_null; break; default: free(logh); return NULL; } logh->priority = priority; netsnmp_enable_this_loghandler(logh); netsnmp_add_loghandler( logh ); return logh; }
/* * create a new row in the table */ netsnmp_tdata_row * tlstmCertToTSNTable_createEntry(netsnmp_tdata * table, u_long tlstmCertToTSNID) { certToTSN_entry *entry; netsnmp_tdata_row *row; entry = SNMP_MALLOC_TYPEDEF(certToTSN_entry); if (!entry) return NULL; row = netsnmp_tdata_create_row(); if (!row) { SNMP_FREE(entry); return NULL; } row->data = entry; DEBUGMSGT(("tlstmCertToSN:entry:create", "entry %p / row %p\n", entry, row)); /* * populate index */ entry->tlstmCertToTSNID = tlstmCertToTSNID; netsnmp_tdata_row_add_index(row, ASN_UNSIGNED, &(entry->tlstmCertToTSNID), sizeof(entry->tlstmCertToTSNID)); /* * assign default column values */ entry->mapType = TSNM_tlstmCertSpecified; entry->storageType = ST_NONVOLATILE; entry->rowStatus = RS_NOTREADY; if (table) { DEBUGMSGTL(("tlstmCertToTSN:row:insert", "row %p\n", row)); netsnmp_tdata_add_row(table, row); } return row; }
netsnmp_tcpconn_entry * netsnmp_access_tcpconn_entry_create(void) { netsnmp_tcpconn_entry *entry = SNMP_MALLOC_TYPEDEF(netsnmp_tcpconn_entry); int rc = 0; DEBUGMSGTL(("verbose:access:tcpconn:entry", "create\n")); entry->oid_index.len = 1; entry->oid_index.oids = &entry->arbitrary_index; /* * init arch data */ rc = netsnmp_arch_tcpconn_entry_init(entry); if (SNMP_ERR_NOERROR != rc) { DEBUGMSGT(("access:tcpconn:create","error %d in arch init\n")); netsnmp_access_tcpconn_entry_free(entry); } return entry; }
static void _iterator_for_each(iterator_info *ii, netsnmp_container_obj_func *f, void *ctx) { netsnmp_ref_void loop_ctx = { NULL }; netsnmp_ref_void tmp = { NULL }; DEBUGMSGT(("container_iterator",">%s\n", "_iterator_foreach")); if(NULL == ii) return; if(ii->init_loop_ctx) ii->init_loop_ctx(ii->user_ctx, &loop_ctx); for( ii->get_first(ii->user_ctx, &loop_ctx, &tmp); NULL != tmp.val; ii->get_next(ii->user_ctx, &loop_ctx, &tmp) ) (*f) (tmp.val, ctx); if(ii->cleanup_loop_ctx) ii->cleanup_loop_ctx(ii->user_ctx,&loop_ctx); }
/** * load initial data * * TODO:350:M: Implement ipv6InterfaceTable data load * * @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 * ipv6InterfaceTable_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 ipv6InterfaceTable_container_load(netsnmp_container *container) { ipv6InterfaceTable_rowreq_ctx *rowreq_ctx; size_t count = 0; /* * temporary storage for index values */ /* * ipv6InterfaceIfIndex(1)/InterfaceIndex/ASN_INTEGER/long(long)//l/a/w/e/R/d/H */ long ipv6InterfaceIfIndex; DEBUGMSGTL(("verbose:ipv6InterfaceTable:ipv6InterfaceTable_container_load", "called\n")); /* * TODO:351:M: |-> Load/update data in the ipv6InterfaceTable container. * loop over your ipv6InterfaceTable data, allocate a rowreq context, * set the index(es) [and data, optionally] and insert into * the container. */ while (1) { /* * check for end of data; bail out if there is no more data */ if (1) break; /* * TODO:352:M: | |-> set indexes in new ipv6InterfaceTable rowreq context. * data context will be set from the param (unless NULL, * in which case a new data context will be allocated) */ rowreq_ctx = ipv6InterfaceTable_allocate_rowreq_ctx(NULL); if (NULL == rowreq_ctx) { snmp_log(LOG_ERR, "memory allocation failed\n"); return MFD_RESOURCE_UNAVAILABLE; } if (MFD_SUCCESS != ipv6InterfaceTable_indexes_set(rowreq_ctx, ipv6InterfaceIfIndex)) { snmp_log(LOG_ERR, "error setting index while loading " "ipv6InterfaceTable data.\n"); ipv6InterfaceTable_release_rowreq_ctx(rowreq_ctx); continue; } /* * TODO:352:r: | |-> populate ipv6InterfaceTable data context. * Populate data context here. (optionally, delay until row prep) */ /* * non-TRANSIENT data: no need to copy. set pointer to data */ /* * insert into table container */ CONTAINER_INSERT(container, rowreq_ctx); ++count; } DEBUGMSGT(("verbose:ipv6InterfaceTable:ipv6InterfaceTable_container_load", "inserted %d records\n", count)); return MFD_SUCCESS; } /* ipv6InterfaceTable_container_load */
/** * * @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; }