X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Ftcpconns.c;h=00cad0e46fa8b4e7857a3c929882a8a6409dacae;hb=55025a66c307823ea3787032c5774afe616d4511;hp=108a4e83df9b74af3bea3837c55523a62bf6b7b9;hpb=83149d73b8a3bd4889517a2e4d0adca0a52e7a06;p=collectd.git diff --git a/src/tcpconns.c b/src/tcpconns.c index 108a4e83..00cad0e4 100644 --- a/src/tcpconns.c +++ b/src/tcpconns.c @@ -23,12 +23,71 @@ #include "common.h" #include "plugin.h" -#if !KERNEL_LINUX +#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME # error "No applicable input method." #endif -#define TCP_STATE_LISTEN 10 -#define TCP_STATE_MAX 11 +#if KERNEL_LINUX +/* #endif KERNEL_LINUX */ + +#elif HAVE_SYSCTLBYNAME +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif /* HAVE_SYSCTLBYNAME */ + +#if KERNEL_LINUX +static const char *tcp_state[] = +{ + "", /* 0 */ + "ESTABLISHED", + "SYN_SENT", + "SYN_RECV", + "FIN_WAIT1", + "FIN_WAIT2", + "TIME_WAIT", + "CLOSED", + "CLOSE_WAIT", + "LAST_ACK", + "LISTEN", /* 10 */ + "CLOSING" +}; + +# define TCP_STATE_LISTEN 10 +# define TCP_STATE_MIN 1 +# define TCP_STATE_MAX 11 +/* #endif KERNEL_LINUX */ + +#elif HAVE_SYSCTLBYNAME +static const char *tcp_state[] = +{ + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RECV", + "ESTABLISHED", + "CLOSE_WAIT", + "FIN_WAIT1", + "CLOSING", + "LAST_ACK", + "FIN_WAIT2", + "TIME_WAIT" +}; + +# define TCP_STATE_LISTEN 1 +# define TCP_STATE_MIN 0 +# define TCP_STATE_MAX 10 +#endif /* HAVE_SYSCTLBYNAME */ #define PORT_COLLECT_LOCAL 0x01 #define PORT_COLLECT_REMOTE 0x02 @@ -51,22 +110,6 @@ static const char *config_keys[] = }; static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); -static const char *tcp_state[] = -{ - "", /* 0 */ - "ESTABLISHED", - "SYN_SENT", - "SYN_RECV", - "FIN_WAIT1", - "FIN_WAIT2", - "TIME_WAIT", - "CLOSE", - "CLOSE_WAIT", - "LAST_ACK", - "LISTEN", /* 10 */ - "CLOSING" -}; - static int port_collect_listening = 0; static port_entry_t *port_list_head = NULL; @@ -196,7 +239,11 @@ static int conn_handle_ports (uint16_t port_local, uint16_t port_remote, uint8_t { port_entry_t *pe = NULL; - if ((state == 0) || (state > TCP_STATE_MAX)) + if ((state > TCP_STATE_MAX) +#if TCP_STATE_MIN > 0 + || (state < TCP_STATE_MIN) +#endif + ) { NOTICE ("tcpconns plugin: Ignoring connection with unknown state 0x%02x.", state); @@ -225,6 +272,7 @@ static int conn_handle_ports (uint16_t port_local, uint16_t port_remote, uint8_t return (0); } /* int conn_handle_ports */ +#if KERNEL_LINUX static int conn_handle_line (char *buffer) { char *fields[32]; @@ -288,12 +336,7 @@ static int conn_read_file (const char *file) fh = fopen (file, "r"); if (fh == NULL) - { - char errbuf[1024]; - ERROR ("tcpconns plugin: fopen (%s) failed: %s", - file, sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); - } while (fgets (buffer, sizeof (buffer), fh) != NULL) { @@ -304,6 +347,10 @@ static int conn_read_file (const char *file) return (0); } /* int conn_read_file */ +/* #endif KERNEL_LINUX */ + +#elif HAVE_SYSCTLBYNAME +#endif /* HAVE_SYSCTLBYNAME */ static int conn_config (const char *key, const char *value) { @@ -348,6 +395,7 @@ static int conn_config (const char *key, const char *value) return (0); } /* int conn_config */ +#if KERNEL_LINUX static int conn_init (void) { if (port_list_head == NULL) @@ -358,21 +406,113 @@ static int conn_init (void) static int conn_read (void) { + int errors_num = 0; + conn_reset_port_entry (); - conn_read_file ("/proc/net/tcp"); - conn_read_file ("/proc/net/tcp6"); + if (conn_read_file ("/proc/net/tcp") != 0) + errors_num++; + if (conn_read_file ("/proc/net/tcp6") != 0) + errors_num++; + + if (errors_num < 2) + { + conn_submit_all (); + } + else + { + ERROR ("tcpconns plugin: Neither /proc/net/tcp nor /proc/net/tcp6 " + "coult be read."); + return (-1); + } + + return (0); +} /* int conn_read */ +/* #endif KERNEL_LINUX */ + +#elif HAVE_SYSCTLBYNAME +static int conn_read (void) +{ + int status; + char *buffer; + size_t buffer_len;; + + struct xinpgen *in_orig; + struct xinpgen *in_ptr; + + conn_reset_port_entry (); + + buffer_len = 0; + status = sysctlbyname ("net.inet.tcp.pcblist", NULL, &buffer_len, 0, 0); + if (status < 0) + { + ERROR ("tcpconns plugin: sysctlbyname failed."); + return (-1); + } + + buffer = (char *) malloc (buffer_len); + if (buffer == NULL) + { + ERROR ("tcpconns plugin: malloc failed."); + return (-1); + } + + status = sysctlbyname ("net.inet.tcp.pcblist", buffer, &buffer_len, 0, 0); + if (status < 0) + { + ERROR ("tcpconns plugin: sysctlbyname failed."); + sfree (buffer); + return (-1); + } + + if (buffer_len <= sizeof (struct xinpgen)) + { + ERROR ("tcpconns plugin: (buffer_len <= sizeof (struct xinpgen))"); + sfree (buffer); + return (-1); + } + + in_orig = (struct xinpgen *) buffer; + for (in_ptr = (struct xinpgen *) (((char *) in_orig) + in_orig->xig_len); + in_ptr->xig_len > sizeof (struct xinpgen); + in_ptr = (struct xinpgen *) (((char *) in_ptr) + in_ptr->xig_len)) + { + struct tcpcb *tp = &((struct xtcpcb *) in_ptr)->xt_tp; + struct inpcb *inp = &((struct xtcpcb *) in_ptr)->xt_inp; + struct xsocket *so = &((struct xtcpcb *) in_ptr)->xt_socket; + + /* Ignore non-TCP sockets */ + if (so->xso_protocol != IPPROTO_TCP) + continue; + + /* Ignore PCBs which were freed during copyout. */ + if (inp->inp_gencnt > in_orig->xig_gen) + continue; + + if (((inp->inp_vflag & INP_IPV4) == 0) + && ((inp->inp_vflag & INP_IPV6) == 0)) + continue; + + conn_handle_ports (inp->inp_lport, inp->inp_fport, tp->t_state); + } /* for (in_ptr) */ + + in_orig = NULL; + in_ptr = NULL; + sfree (buffer); conn_submit_all (); return (0); } /* int conn_read */ +#endif /* HAVE_SYSCTLBYNAME */ void module_register (void) { plugin_register_config ("tcpconns", conn_config, config_keys, config_keys_num); +#if KERNEL_LINUX plugin_register_init ("tcpconns", conn_init); +#endif plugin_register_read ("tcpconns", conn_read); } /* void module_register */