diff options
Diffstat (limited to 'agent/mibgroup/ip-mib/data_access/ipaddress_common.c')
-rw-r--r-- | agent/mibgroup/ip-mib/data_access/ipaddress_common.c | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/agent/mibgroup/ip-mib/data_access/ipaddress_common.c b/agent/mibgroup/ip-mib/data_access/ipaddress_common.c new file mode 100644 index 0000000..396fc96 --- /dev/null +++ b/agent/mibgroup/ip-mib/data_access/ipaddress_common.c @@ -0,0 +1,430 @@ +/* + * Ipaddress MIB architecture support + * + * $Id: ipaddress_common.c 16724 2007-10-14 22:10:09Z magfr $ + */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> + +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include <net-snmp/data_access/ipaddress.h> +#include <net-snmp/data_access/interface.h> + +#include "ip-mib/ipAddressTable/ipAddressTable_constants.h" + +/**---------------------------------------------------------------------*/ +/* + * local static prototypes + */ +static int _access_ipaddress_entry_compare_addr(const void *lhs, + const void *rhs); +static void _access_ipaddress_entry_release(netsnmp_ipaddress_entry * entry, + void *unused); + +/**---------------------------------------------------------------------*/ +/* + * external per-architecture functions prototypes + * + * These shouldn't be called by the general public, so they aren't in + * the header file. + */ +extern int +netsnmp_arch_ipaddress_container_load(netsnmp_container* container, + u_int load_flags); +extern int +netsnmp_arch_ipaddress_entry_init(netsnmp_ipaddress_entry *entry); +extern int +netsnmp_arch_ipaddress_entry_copy(netsnmp_ipaddress_entry *lhs, + netsnmp_ipaddress_entry *rhs); +extern void +netsnmp_arch_ipaddress_entry_cleanup(netsnmp_ipaddress_entry *entry); +extern int +netsnmp_arch_ipaddress_create(netsnmp_ipaddress_entry *entry); +extern int +netsnmp_arch_ipaddress_delete(netsnmp_ipaddress_entry *entry); + + +/**---------------------------------------------------------------------*/ +/* + * container functions + */ +/** + */ +netsnmp_container * +netsnmp_access_ipaddress_container_init(u_int flags) +{ + netsnmp_container *container1; + + DEBUGMSGTL(("access:ipaddress:container", "init\n")); + + /* + * create the containers. one indexed by ifIndex, the other + * indexed by ifName. + */ + container1 = netsnmp_container_find("access_ipaddress:table_container"); + if (NULL == container1) { + snmp_log(LOG_ERR, "ipaddress primary container not found\n"); + return NULL; + } + container1->container_name = strdup("ia_index"); + + if (flags & NETSNMP_ACCESS_IPADDRESS_INIT_ADDL_IDX_BY_ADDR) { + netsnmp_container *container2 = + netsnmp_container_find("ipaddress_addr:access_ipaddress:table_container"); + if (NULL == container2) { + snmp_log(LOG_ERR, "ipaddress secondary container not found\n"); + CONTAINER_FREE(container1); + return NULL; + } + + container2->compare = _access_ipaddress_entry_compare_addr; + container2->container_name = strdup("ia_addr"); + + netsnmp_container_add_index(container1, container2); + } + + return container1; +} + +/** + * @retval NULL error + * @retval !NULL pointer to container + */ +netsnmp_container* +netsnmp_access_ipaddress_container_load(netsnmp_container* container, + u_int load_flags) +{ + int rc; + u_int container_flags = 0; + + DEBUGMSGTL(("access:ipaddress:container", "load\n")); + + if (NULL == container) { + if (load_flags & NETSNMP_ACCESS_IPADDRESS_LOAD_ADDL_IDX_BY_ADDR) + container_flags |= NETSNMP_ACCESS_IPADDRESS_INIT_ADDL_IDX_BY_ADDR; + container = netsnmp_access_ipaddress_container_init(container_flags); + } + if (NULL == container) { + snmp_log(LOG_ERR, "no container specified/found for access_ipaddress\n"); + return NULL; + } + + rc = netsnmp_arch_ipaddress_container_load(container, load_flags); + if (0 != rc) { + netsnmp_access_ipaddress_container_free(container, + NETSNMP_ACCESS_IPADDRESS_FREE_NOFLAGS); + container = NULL; + } + + return container; +} + +void +netsnmp_access_ipaddress_container_free(netsnmp_container *container, u_int free_flags) +{ + DEBUGMSGTL(("access:ipaddress:container", "free\n")); + + if (NULL == container) { + snmp_log(LOG_ERR, "invalid container for netsnmp_access_ipaddress_free\n"); + return; + } + + if(! (free_flags & NETSNMP_ACCESS_IPADDRESS_FREE_DONT_CLEAR)) { + /* + * free all items. + */ + CONTAINER_CLEAR(container, + (netsnmp_container_obj_func*)_access_ipaddress_entry_release, + NULL); + } + + if(! (free_flags & NETSNMP_ACCESS_IPADDRESS_FREE_KEEP_CONTAINER)) + CONTAINER_FREE(container); +} + +/**---------------------------------------------------------------------*/ +/* + * ipaddress_entry functions + */ +/** + */ +/** + */ +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", rc)); + netsnmp_access_ipaddress_entry_free(entry); + entry = NULL; + } + + return entry; +} + +/** + */ +void +netsnmp_access_ipaddress_entry_free(netsnmp_ipaddress_entry * entry) +{ + if (NULL == entry) + return; + + if (NULL != entry->arch_data) + netsnmp_arch_ipaddress_entry_cleanup(entry); + + free(entry); +} + +/** + * update underlying data store (kernel) for entry + * + * @retval 0 : success + * @retval -1 : error + */ +int +netsnmp_access_ipaddress_entry_set(netsnmp_ipaddress_entry * entry) +{ + int rc = SNMP_ERR_NOERROR; + + if (NULL == entry) { + netsnmp_assert(NULL != entry); + return -1; + } + + /* + * make sure interface and ifIndex match up + */ + if (NULL == netsnmp_access_interface_name_find(entry->if_index)) { + DEBUGMSGT(("access:ipaddress:set", "cant find name for index %d\n", + entry->if_index)); + return -1; + } + + /* + * don't support non-volatile yet + */ + if (STORAGETYPE_VOLATILE != entry->ia_storagetype) { + DEBUGMSGT(("access:ipaddress:set", + "non-volatile storagetypes unsupported\n")); + return -1; + } + + /* + * + */ + rc = -1; + if (entry->flags & NETSNMP_ACCESS_IPADDRESS_CREATE) { + rc = netsnmp_arch_ipaddress_create(entry); + } + else if (entry->flags & NETSNMP_ACCESS_IPADDRESS_CHANGE) { + } + else if (entry->flags & NETSNMP_ACCESS_IPADDRESS_DELETE) { + rc = netsnmp_arch_ipaddress_delete(entry); + } + else { + snmp_log(LOG_ERR,"netsnmp_access_ipaddress_entry_set with no mode\n"); + netsnmp_assert(!"ipaddress_entry_set == unknown mode"); /* always false */ + rc = -1; + } + + return rc; +} + +/** + * update an old ipaddress_entry from a new one + * + * @note: only mib related items are compared. Internal objects + * such as oid_index, ns_ia_index and flags are not compared. + * + * @retval -1 : error + * @retval >=0 : number of fields updated + */ +int +netsnmp_access_ipaddress_entry_update(netsnmp_ipaddress_entry *lhs, + netsnmp_ipaddress_entry *rhs) +{ + int rc, changed = 0; + + /* + * copy arch stuff. we don't care if it changed + */ + rc = netsnmp_arch_ipaddress_entry_copy(lhs,rhs); + if (0 != rc) { + snmp_log(LOG_ERR,"arch ipaddress copy failed\n"); + return -1; + } + + if (lhs->if_index != rhs->if_index) { + ++changed; + lhs->if_index = rhs->if_index; + } + + if (lhs->ia_storagetype != rhs->ia_storagetype) { + ++changed; + lhs->ia_storagetype = rhs->ia_storagetype; + } + + if (lhs->ia_address_len != rhs->ia_address_len) { + changed += 2; + lhs->ia_address_len = rhs->ia_address_len; + memcpy(lhs->ia_address, rhs->ia_address, rhs->ia_address_len); + } + else if (memcmp(lhs->ia_address, rhs->ia_address, rhs->ia_address_len) != 0) { + ++changed; + memcpy(lhs->ia_address, rhs->ia_address, rhs->ia_address_len); + } + + if (lhs->ia_type != rhs->ia_type) { + ++changed; + lhs->ia_type = rhs->ia_type; + } + + if (lhs->ia_status != rhs->ia_status) { + ++changed; + lhs->ia_status = rhs->ia_status; + } + + if (lhs->ia_origin != rhs->ia_origin) { + ++changed; + lhs->ia_origin = rhs->ia_origin; + } + + return changed; +} + +/** + * copy an ipaddress_entry + * + * @retval -1 : error + * @retval 0 : no error + */ +int +netsnmp_access_ipaddress_entry_copy(netsnmp_ipaddress_entry *lhs, + netsnmp_ipaddress_entry *rhs) +{ + int rc; + + /* + * copy arch stuff. we don't care if it changed + */ + rc = netsnmp_arch_ipaddress_entry_copy(lhs,rhs); + if (0 != rc) { + snmp_log(LOG_ERR,"arch ipaddress copy failed\n"); + return -1; + } + + lhs->if_index = rhs->if_index; + lhs->ia_storagetype = rhs->ia_storagetype; + lhs->ia_address_len = rhs->ia_address_len; + memcpy(lhs->ia_address, rhs->ia_address, rhs->ia_address_len); + lhs->ia_type = rhs->ia_type; + lhs->ia_status = rhs->ia_status; + lhs->ia_origin = rhs->ia_origin; + + return 0; +} + +/**---------------------------------------------------------------------*/ +/* + * Utility routines + */ + +/** + * copy the prefix portion of an ip address + */ +int +netsnmp_ipaddress_prefix_copy(u_char *dst, u_char *src, int addr_len, int pfx_len) +{ + int bytes = pfx_len / 8; + int bits = pfx_len % 8; + + if ((NULL == dst) || (NULL == src) || (0 == pfx_len)) + return 0; + + memcpy(dst, src, bytes); + + if (bytes < addr_len) + memset(&dst[bytes],0x0, addr_len - bytes); + + if (bits) { + u_char mask = (0xff << (8-bits)); + + dst[bytes] = (src[bytes] & mask); + } + + return pfx_len; +} + + +/** + * copy the prefix portion of an ip address + * + * @param mask network byte order make + * + * @returns number of prefix bits + */ +int +netsnmp_ipaddress_ipv4_prefix_len(in_addr_t mask) +{ + int len = 0; + + while((0xff000000 & mask) == 0xff000000) { + len += 8; + mask = mask << 8; + } + + while(0x80000000 & mask) { + ++len; + mask = mask << 1; + } + + return len; +} + + +/** + */ +void +_access_ipaddress_entry_release(netsnmp_ipaddress_entry * entry, void *context) +{ + netsnmp_access_ipaddress_entry_free(entry); +} + +static int _access_ipaddress_entry_compare_addr(const void *lhs, + const void *rhs) +{ + const netsnmp_ipaddress_entry *lh = (const netsnmp_ipaddress_entry *)lhs; + const netsnmp_ipaddress_entry *rh = (const netsnmp_ipaddress_entry *)rhs; + + netsnmp_assert(NULL != lhs); + netsnmp_assert(NULL != rhs); + + /* + * compare address length + */ + if (lh->ia_address_len < rh->ia_address_len) + return -1; + else if (lh->ia_address_len > rh->ia_address_len) + return 1; + + /* + * length equal, compare address + */ + return memcmp(lh->ia_address, rh->ia_address, lh->ia_address_len); +} |