| /* |
| * tcpConnTable 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/data_access/tcpConn.h> |
| |
| #include "tcp-mib/tcpConnectionTable/tcpConnectionTable_constants.h" |
| #include "tcp-mib/data_access/tcpConn_private.h" |
| #include "mibgroup/util_funcs/get_pid_from_inode.h" |
| static int |
| linux_states[12] = { 1, 5, 3, 4, 6, 7, 11, 1, 8, 9, 2, 10 }; |
| |
| 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_tcpconn_entry_init(netsnmp_tcpconn_entry *entry) |
| { |
| /* |
| * init |
| */ |
| return 0; |
| } |
| |
| /* |
| * cleanup arch specific storage |
| */ |
| void |
| netsnmp_arch_tcpconn_entry_cleanup(netsnmp_tcpconn_entry *entry) |
| { |
| /* |
| * cleanup |
| */ |
| } |
| |
| /* |
| * copy arch specific storage |
| */ |
| int |
| netsnmp_arch_tcpconn_entry_copy(netsnmp_tcpconn_entry *lhs, |
| netsnmp_tcpconn_entry *rhs) |
| { |
| return 0; |
| } |
| |
| /* |
| * delete an entry |
| */ |
| int |
| netsnmp_arch_tcpconn_delete(netsnmp_tcpconn_entry *entry) |
| { |
| if (NULL == entry) |
| return -1; |
| /** xxx-rks:9 tcpConn delete not implemented */ |
| return -1; |
| } |
| |
| |
| /** |
| * |
| * @retval 0 no errors |
| * @retval !0 errors |
| */ |
| int |
| netsnmp_arch_tcpconn_container_load(netsnmp_container *container, |
| u_int load_flags ) |
| { |
| int rc = 0; |
| |
| DEBUGMSGTL(("access:tcpconn:container", |
| "tcpconn_container_arch_load (flags %x)\n", load_flags)); |
| |
| if (NULL == container) { |
| snmp_log(LOG_ERR, "no container specified/found for access_tcpconn\n"); |
| return -1; |
| } |
| |
| rc = _load4(container, load_flags); |
| |
| #if defined (NETSNMP_ENABLE_IPV6) |
| if((0 != rc) || (load_flags & NETSNMP_ACCESS_TCPCONN_LOAD_IPV4_ONLY)) |
| return rc; |
| |
| /* |
| * load ipv6. ipv6 module might not be loaded, |
| * so ignore -2 err (file not found) |
| */ |
| rc = _load6(container, load_flags); |
| if (-2 == rc) |
| rc = 0; |
| #endif |
| |
| return rc; |
| } |
| |
| /** |
| * |
| * @retval 0 no errors |
| * @retval !0 errors |
| */ |
| static int |
| _load4(netsnmp_container *container, u_int load_flags) |
| { |
| int rc = 0; |
| FILE *in; |
| char line[160]; |
| |
| netsnmp_assert(NULL != container); |
| |
| #define PROCFILE "/proc/net/tcp" |
| if (!(in = fopen(PROCFILE, "r"))) { |
| snmp_log(LOG_ERR,"could not open " PROCFILE "\n"); |
| return -2; |
| } |
| |
| fgets(line, sizeof(line), in); /* skip header */ |
| |
| /* |
| * sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode |
| * 0: 00000000:8000 00000000:0000 0A 00000000:00000000 00:00000000 00000000 29 0 1028 1 df7b1b80 300 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[10], remote_addr[10]; |
| u_char *tmp_ptr; |
| |
| if (6 != (rc = sscanf(line, "%*d: %8[0-9A-Z]:%x %8[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)); |
| snmp_log(LOG_ERR, "tcp:_load4: bad line in " PROCFILE ": %s\n", line); |
| rc = 0; |
| 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 ((8 != buf_len) || |
| (-1 == netsnmp_addrstr_hton(local_addr, 8))) { |
| 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 ( 4 != entry->loc_addr_len ) { |
| DEBUGMSGT(("access:tcpconn:container", |
| "error parsing local addr (%d != 4)\n", |
| entry->loc_addr_len)); |
| DEBUGMSGT(("access:tcpconn:container"," line '%s'\n", line)); |
| netsnmp_access_tcpconn_entry_free(entry); |
| continue; |
| } |
| |
| /** the addr string may need work */ |
| buf_len = strlen((char*)remote_addr); |
| if ((8 != buf_len) || |
| (-1 == netsnmp_addrstr_hton(remote_addr, 8))) { |
| 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 ( 4 != entry->rmt_addr_len ) { |
| DEBUGMSGT(("access:tcpconn:container", |
| "error parsing remote addr (%d != 4)\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; |
| } |
| |
| #if defined (NETSNMP_ENABLE_IPV6) |
| /** |
| * |
| * @retval 0 no errors |
| * @retval !0 errors |
| */ |
| static int |
| _load6(netsnmp_container *container, u_int load_flags) |
| { |
| int rc = 0; |
| FILE *in; |
| char line[360]; |
| |
| netsnmp_assert(NULL != container); |
| |
| #undef PROCFILE |
| #define PROCFILE "/proc/net/tcp6" |
| if (!(in = fopen(PROCFILE, "r"))) { |
| DEBUGMSGTL(("access:tcpconn:container","could not open " PROCFILE "\n")); |
| return -2; |
| } |
| |
| 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, 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)); |
| snmp_log(LOG_ERR, "tcp:_load6: bad line in " PROCFILE ": %s\n", line); |
| rc = 0; |
| 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; |
| } |
| #endif /* NETSNMP_ENABLE_IPV6 */ |