From: Florian Forster Date: Mon, 22 Oct 2007 21:03:12 +0000 (+0200) Subject: tcpconns plugin: Added support for Mac OS X (and possibly FreeBSD). X-Git-Tag: collectd-4.2.0~21^2~4 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=1695cd0763cb407e5606c27ce32c6054125fb560;p=collectd.git tcpconns plugin: Added support for Mac OS X (and possibly FreeBSD). --- diff --git a/configure.in b/configure.in index d128d5e2..4dc04b0e 100644 --- a/configure.in +++ b/configure.in @@ -1759,6 +1759,7 @@ if test "x$have_sysctlbyname" = "xyes" then plugin_cpu="yes" plugin_memory="yes" + plugin_tcpconns="yes" fi if test "x$have_statfs" = "xyes" diff --git a/src/tcpconns.c b/src/tcpconns.c index 108a4e83..74874ae3 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]; @@ -304,6 +352,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 +400,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) @@ -367,12 +420,91 @@ static int conn_read (void) 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 */