| /* |
| * udpEndpointTable MIB architecture support |
| * |
| * $Id$ |
| */ |
| #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/library/file_utils.h> |
| #include <net-snmp/library/text_utils.h> |
| |
| #include <net-snmp/data_access/ipaddress.h> |
| #include <net-snmp/data_access/udp_endpoint.h> |
| |
| #include "udp-mib/udpEndpointTable/udpEndpointTable_constants.h" |
| |
| #include "udp_endpoint_private.h" |
| |
| #include <fcntl.h> |
| |
| static int _load4(netsnmp_container *container, u_int flags); |
| #if defined (NETSNMP_ENABLE_IPV6) |
| static int _load6(netsnmp_container *container, u_int flags); |
| #endif |
| |
| /* |
| * initialize arch specific storage |
| * |
| * @retval 0: success |
| * @retval <0: error |
| */ |
| int |
| netsnmp_arch_udp_endpoint_entry_init(netsnmp_udp_endpoint_entry *entry) |
| { |
| /* |
| * init |
| */ |
| return 0; |
| } |
| |
| /* |
| * cleanup arch specific storage |
| */ |
| void |
| netsnmp_arch_udp_endpoint_entry_cleanup(netsnmp_udp_endpoint_entry *entry) |
| { |
| /* |
| * cleanup |
| */ |
| } |
| |
| /* |
| * copy arch specific storage |
| */ |
| int |
| netsnmp_arch_udp_endpoint_entry_copy(netsnmp_udp_endpoint_entry *lhs, |
| netsnmp_udp_endpoint_entry *rhs) |
| { |
| return 0; |
| } |
| |
| /* |
| * delete an entry |
| */ |
| int |
| netsnmp_arch_udp_endpoint_delete(netsnmp_udp_endpoint_entry *entry) |
| { |
| if (NULL == entry) |
| return -1; |
| /** xxx-rks:9 udp_endpoint delete not implemented */ |
| return -1; |
| } |
| |
| |
| /** |
| * |
| * @retval 0 no errors |
| * @retval !0 errors |
| */ |
| int |
| netsnmp_arch_udp_endpoint_container_load(netsnmp_container *container, |
| u_int load_flags ) |
| { |
| int rc = 0; |
| |
| rc = _load4(container, load_flags); |
| if(rc < 0) { |
| u_int flags = NETSNMP_ACCESS_UDP_ENDPOINT_FREE_KEEP_CONTAINER; |
| netsnmp_access_udp_endpoint_container_free(container, flags); |
| return rc; |
| } |
| |
| #if defined (NETSNMP_ENABLE_IPV6) |
| rc = _load6(container, load_flags); |
| if(rc < 0) { |
| u_int flags = NETSNMP_ACCESS_UDP_ENDPOINT_FREE_KEEP_CONTAINER; |
| netsnmp_access_udp_endpoint_container_free(container, flags); |
| return rc; |
| } |
| #endif |
| |
| return 0; |
| } |
| |
| /** |
| * @internal |
| * process token value index line |
| */ |
| static int |
| _process_line_udp_ep(netsnmp_line_info *line_info, void *mem, |
| struct netsnmp_line_process_info_s* lpi) |
| { |
| netsnmp_udp_endpoint_entry *ep = (netsnmp_udp_endpoint_entry *)mem; |
| char *ptr, *sep; |
| u_char *u_ptr; |
| size_t u_ptr_len, offset, len; |
| unsigned long long inode; |
| size_t count = 0; |
| |
| /* |
| * skip 'sl' |
| */ |
| ptr = skip_not_white(line_info->start); |
| if (NULL == ptr) { |
| DEBUGMSGTL(("access:udp_endpoint", "no sl '%s'\n", |
| line_info->start)); |
| return PMLP_RC_MEMORY_UNUSED; |
| } |
| ptr = skip_white(ptr); |
| if (NULL == ptr) { |
| DEBUGMSGTL(("text:util:tvi", "no space after sl '%s'\n", |
| line_info->start)); |
| return PMLP_RC_MEMORY_UNUSED; |
| } |
| |
| /* |
| * get local address. ignore error on hex conversion, since that |
| * function doesn't like the ':' between address and port. check the |
| * offset to see if it worked. May need to flip string too. |
| */ |
| u_ptr = ep->loc_addr; |
| u_ptr_len = sizeof(ep->loc_addr); |
| sep = strchr(ptr, ':'); |
| if (NULL == sep) { |
| DEBUGMSGTL(("text:util:tvi", "no ':' '%s'\n", |
| line_info->start)); |
| return PMLP_RC_MEMORY_UNUSED; |
| } |
| len = (sep - ptr); |
| if (-1 == netsnmp_addrstr_hton(ptr, len)) { |
| DEBUGMSGTL(("text:util:tvi", "bad length %d for loc addr '%s'\n", |
| u_ptr_len, line_info->start)); |
| return PMLP_RC_MEMORY_UNUSED; |
| } |
| offset = 0; |
| netsnmp_hex_to_binary(&u_ptr, &u_ptr_len, &offset, 0, ptr, NULL); |
| if ((4 != offset) && (16 != offset)) { |
| DEBUGMSGTL(("text:util:tvi", "bad offset %d for loc addr '%s'\n", |
| offset, line_info->start)); |
| return PMLP_RC_MEMORY_UNUSED; |
| } |
| ep->loc_addr_len = offset; |
| ptr += (offset * 2); |
| ++ptr; /* skip ':' */ |
| |
| /* |
| * get local port |
| */ |
| ep->loc_port = strtol(ptr, &ptr, 16); |
| ptr = skip_white(ptr); |
| |
| /* |
| * get remote address. ignore error on hex conversion, since that |
| * function doesn't like the ':' between address and port. check the |
| * offset to see if it worked. May need to flip string too. |
| */ |
| u_ptr = ep->rmt_addr; |
| u_ptr_len = sizeof(ep->rmt_addr); |
| sep = strchr(ptr, ':'); |
| if (NULL == sep) { |
| DEBUGMSGTL(("text:util:tvi", "no ':' '%s'\n", |
| line_info->start)); |
| return PMLP_RC_MEMORY_UNUSED; |
| } |
| len = (sep - ptr); |
| if (-1 == netsnmp_addrstr_hton(ptr, len)) { |
| DEBUGMSGTL(("text:util:tvi", "bad length %d for rmt addr '%s'\n", |
| u_ptr_len, line_info->start)); |
| return PMLP_RC_MEMORY_UNUSED; |
| } |
| offset = 0; |
| netsnmp_hex_to_binary(&u_ptr, &u_ptr_len, &offset, 0, ptr, NULL); |
| if ((4 != offset) && (16 != offset)) { |
| DEBUGMSGTL(("text:util:tvi", "bad offset %d for rmt addr '%s'\n", |
| offset, line_info->start)); |
| return PMLP_RC_MEMORY_UNUSED; |
| } |
| ep->rmt_addr_len = offset; |
| ptr += (offset * 2); |
| ++ptr; /* skip ':' */ |
| |
| /* |
| * get remote port |
| */ |
| ep->rmt_port = strtol(ptr, &ptr, 16); |
| ptr = skip_white(ptr); |
| |
| /* |
| * get state too |
| */ |
| ep->state = strtol(ptr, &ptr, 16); |
| |
| /* |
| * Use inode as instance value. |
| */ |
| while (count != 5) { |
| ptr = skip_white(ptr); |
| ptr = skip_not_white(ptr); |
| count++; |
| } |
| inode = strtoull(ptr, &ptr, 0); |
| ep->instance = (u_int)inode; |
| |
| ep->index = (u_int)(lpi->user_context); |
| lpi->user_context = (void*)((u_int)(lpi->user_context) + 1); |
| |
| ep->oid_index.oids = &ep->index; |
| ep->oid_index.len = 1; |
| |
| return PMLP_RC_MEMORY_USED; |
| } |
| |
| /** |
| * |
| * @retval 0 no errors |
| * @retval !0 errors |
| */ |
| static int |
| _load4(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/udp" , 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*)0; |
| |
| container = netsnmp_file_text_parse(fp, container, PM_USER_FUNCTION, |
| 0, &lpi); |
| netsnmp_file_release(fp); |
| return (NULL == container); |
| } |
| |
| #if defined (NETSNMP_ENABLE_IPV6) |
| /** |
| * |
| * @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); |
| } |
| #endif /* NETSNMP_ENABLE_IPV6 */ |