From: Manuel Luis SanmartĂ­n Rozada Date: Mon, 6 Jun 2011 12:14:27 +0000 (+0200) Subject: tcpconns plugin: add support for AIX X-Git-Tag: collectd-5.1.0~52 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=95b08a826445423b00297d0db8cfb9676b5f676d;p=collectd.git tcpconns plugin: add support for AIX Hi. In AIX there is a undocumented function/syscall in libc: netinfo returns a structure with the state of the tcp connections. I didn't found the description or info abut this syscall, I guess is something like this: int netinfo (int proto, void *data, int *size, int n); and the struct something like this: (with some work we can guess the unknow remaining bytes) struct netinfo_header { unsigned int proto; unsigned int size; struct netinfo_entry e[]; }; struct netinfo_entry { uint32_t unknow1; uint32_t unknow2; uint16_t dstport; uint16_t unknow3; struct in6_addr dstaddr; uint16_t srcport; uint16_t unknow4; struct in6_addr srcaddr; uint32_t unknow01[4]; uint32_t unknow02[2]; uint16_t so_options; uint16_t unknow02a; uint16_t so_q0len; uint16_t so_qlen; uint16_t so_qlimit; uint16_t so_dqlen; uint32_t unknow03[4]; struct { uint32_t sb_hiwat; uint32_t unknow01; uint32_t unknow02; uint32_t unknow03; uint32_t sb_mbmax; uint32_t unknow04; uint32_t sb_lowat; uint16_t sb_flags; uint16_t unknow05; } rcvbuf; uint32_t unknow07; uint32_t unknow08[2]; uint32_t unknow09; struct { uint32_t sb_hiwat; uint32_t unknow01; uint32_t unknow02; uint32_t unknow03; uint32_t sb_mbmax; uint32_t unknow04; uint32_t sb_lowat; uint16_t sb_flags; uint16_t unknow05; } sndbuf; uint32_t unknow11; uint32_t so_uid; uint16_t so_special; uint16_t so_special2; uint16_t tcp_state; uint16_t unknow12; uint32_t tcp_flags; uint32_t tcp_mss; uint32_t unknow15; }; Signed-off-by: Florian Forster --- diff --git a/configure.in b/configure.in index 3b641d16..9b6397f8 100644 --- a/configure.in +++ b/configure.in @@ -4358,6 +4358,12 @@ then fi # AIX + +if test "x$ac_system" = "xAIX" +then + plugin_tcpconns="yes" +fi + if test "x$with_perfstat" = "xyes" then plugin_cpu="yes" diff --git a/src/tcpconns.c b/src/tcpconns.c index d68cd096..6a7e32d7 100644 --- a/src/tcpconns.c +++ b/src/tcpconns.c @@ -65,7 +65,7 @@ #undef HAVE_SYSCTLBYNAME /* force HAVE_LIBKVM_NLIST path */ #endif -#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !HAVE_LIBKVM_NLIST +#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !HAVE_LIBKVM_NLIST && !KERNEL_AIX # error "No applicable input method." #endif @@ -118,7 +118,12 @@ # include # include # include -#endif /* HAVE_LIBKVM_NLIST */ +/* #endif HAVE_LIBKVM_NLIST */ + +#elif KERNEL_AIX +# include +# include +#endif /* KERNEL_AIX */ #if KERNEL_LINUX static const char *tcp_state[] = @@ -186,7 +191,49 @@ struct inpcbtable *inpcbtable_ptr = NULL; # define TCP_STATE_LISTEN 1 # define TCP_STATE_MIN 1 # define TCP_STATE_MAX 10 -#endif /* HAVE_LIBKVM_NLIST */ +/* #endif HAVE_LIBKVM_NLIST */ + +#elif KERNEL_AIX +static const char *tcp_state[] = +{ + "CLOSED", + "LISTEN", + "SYN_SENT", + "SYN_RCVD", + "ESTABLISHED", + "CLOSE_WAIT", + "FIN_WAIT_1", + "CLOSING", + "LAST_ACK", + "FIN_WAIT_2", + "TIME_WAIT" +}; + +# define TCP_STATE_LISTEN 1 +# define TCP_STATE_MIN 0 +# define TCP_STATE_MAX 10 + +struct netinfo_conn { + uint32_t unknow1[2]; + uint16_t dstport; + uint16_t unknow2; + struct in6_addr dstaddr; + uint16_t srcport; + uint16_t unknow3; + struct in6_addr srcaddr; + uint32_t unknow4[36]; + uint16_t tcp_state; + uint16_t unknow5[7]; +}; + +struct netinfo_header { + unsigned int proto; + unsigned int size; +}; + +# define NETINFO_TCP 3 +extern int netinfo (int proto, void *data, int *size, int n); +#endif /* KERNEL_AIX */ #define PORT_COLLECT_LOCAL 0x01 #define PORT_COLLECT_REMOTE 0x02 @@ -706,7 +753,67 @@ static int conn_read (void) return (0); } -#endif /* HAVE_LIBKVM_NLIST */ +/* #endif HAVE_LIBKVM_NLIST */ + +#elif KERNEL_AIX + +static int conn_read (void) +{ + int size; + int i; + int nconn; + void *data; + struct netinfo_header *header; + struct netinfo_conn *conn; + + conn_reset_port_entry (); + + size = netinfo(NETINFO_TCP, 0, 0, 0); + if (size < 0) + { + ERROR ("tcpconns plugin: netinfo failed return: %i", size); + return (-1); + } + + if (size == 0) + return (0); + + if ((size - sizeof (struct netinfo_header)) % sizeof (struct netinfo_conn)) + { + ERROR ("tcpconns plugin: invalid buffer size"); + return (-1); + } + + data = malloc(size); + if (data == NULL) + { + ERROR ("tcpconns plugin: malloc failed"); + return (-1); + } + + if (netinfo(NETINFO_TCP, data, &size, 0) < 0) + { + ERROR ("tcpconns plugin: netinfo failed"); + free(data); + return (-1); + } + + header = (struct netinfo_header *)data; + nconn = header->size; + conn = (struct netinfo_conn *)(data + sizeof(struct netinfo_header)); + + for (i=0; i < nconn; conn++, i++) + { + conn_handle_ports (conn->srcport, conn->dstport, conn->tcp_state); + } + + free(data); + + conn_submit_all (); + + return (0); +} +#endif /* KERNEL_AIX */ void module_register (void) { @@ -718,6 +825,8 @@ void module_register (void) /* no initialization */ #elif HAVE_LIBKVM_NLIST plugin_register_init ("tcpconns", conn_init); +#elif KERNEL_AIX + /* no initialization */ #endif plugin_register_read ("tcpconns", conn_read); } /* void module_register */