summaryrefslogtreecommitdiff
path: root/agent/mibgroup/tcp-mib/data_access/tcpConn_linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/tcp-mib/data_access/tcpConn_linux.c')
-rw-r--r--agent/mibgroup/tcp-mib/data_access/tcpConn_linux.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/agent/mibgroup/tcp-mib/data_access/tcpConn_linux.c b/agent/mibgroup/tcp-mib/data_access/tcpConn_linux.c
new file mode 100644
index 0000000..26c9a73
--- /dev/null
+++ b/agent/mibgroup/tcp-mib/data_access/tcpConn_linux.c
@@ -0,0 +1,392 @@
+/*
+ * 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;
+}
+
+#ifdef TCPCONN_DELETE_SUPPORTED
+/*
+ * delete an entry
+ */
+int
+netsnmp_arch_tcpconn_entry_delete(netsnmp_tcpconn_entry *entry)
+{
+ if (NULL == entry)
+ return -1;
+ /** xxx-rks:9 tcpConn delete not implemented */
+ return -1;
+}
+#endif /* TCPCONN_DELETE_SUPPORTED */
+
+/**
+ *
+ * @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));
+
+ /* Setup the pid_from_inode table, and fill it.*/
+ netsnmp_get_pid_from_inode_init();
+
+ 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;
+ unsigned int state, 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));
+ 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[180];
+
+ 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));
+ 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 */