Merge branch 'collectd-5.5'
[collectd.git] / src / tcpconns.c
index 8fbc1a4..5b47ff5 100644 (file)
@@ -17,7 +17,7 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  *
  * Author:
- *   Florian octo Forster <octo at verplant.org>
+ *   Florian octo Forster <octo at collectd.org>
  *   Michael Stapelberg <michael+git at stapelberg.de>
  **/
 
 
 #if KERNEL_LINUX
 # include <asm/types.h>
-/* sys/socket.h is necessary to compile when using netlink on older systems. */
-# include <sys/socket.h>
 # include <linux/netlink.h>
+#if HAVE_LINUX_INET_DIAG_H
 # include <linux/inet_diag.h>
-# include <sys/socket.h>
+#endif
 # include <arpa/inet.h>
 /* #endif KERNEL_LINUX */
 
@@ -88,9 +87,6 @@
 #if HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
 #if HAVE_NET_IF_H
 # include <net/if.h>
 #endif
 /* This is for OpenBSD and NetBSD. */
 #elif HAVE_LIBKVM_NLIST
 # include <sys/queue.h>
-# include <sys/socket.h>
 # include <net/route.h>
 # include <netinet/in.h>
 # include <netinet/in_systm.h>
 #endif /* KERNEL_AIX */
 
 #if KERNEL_LINUX
+#if HAVE_STRUCT_LINUX_INET_DIAG_REQ
 struct nlreq {
   struct nlmsghdr nlh;
   struct inet_diag_req r;
 };
+#endif
 
 static const char *tcp_state[] =
 {
@@ -215,13 +212,13 @@ static const char *tcp_state[] =
   "CLOSED",
   "LISTEN",
   "SYN_SENT",
-  "SYN_RCVD",
+  "SYN_RECV",
   "ESTABLISHED",
   "CLOSE_WAIT",
-  "FIN_WAIT_1",
+  "FIN_WAIT1",
   "CLOSING",
   "LAST_ACK",
-  "FIN_WAIT_2",
+  "FIN_WAIT2",
   "TIME_WAIT"
 };
 
@@ -279,9 +276,14 @@ static port_entry_t *port_list_head = NULL;
 static uint32_t count_total[TCP_STATE_MAX + 1];
 
 #if KERNEL_LINUX
+#if HAVE_STRUCT_LINUX_INET_DIAG_REQ
+/* This depends on linux inet_diag_req because if this structure is missing,
+ * sequence_number is useless and we get a compilation warning.
+ */
 static uint32_t sequence_number = 0;
+#endif
 
-enum
+static enum
 {
   SRC_DUNNO,
   SRC_NETLINK,
@@ -410,18 +412,18 @@ static void conn_reset_port_entry (void)
     /* If this entry was created while reading the files (ant not when handling
      * the configuration) remove it now. */
     if ((pe->flags & (PORT_COLLECT_LOCAL
-           | PORT_COLLECT_REMOTE
-           | PORT_IS_LISTENING)) == 0)
+            | PORT_COLLECT_REMOTE
+            | PORT_IS_LISTENING)) == 0)
     {
       port_entry_t *next = pe->next;
 
       DEBUG ("tcpconns plugin: Removing temporary entry "
-         "for listening port %"PRIu16, pe->port);
+          "for listening port %"PRIu16, pe->port);
 
       if (prev == NULL)
-       port_list_head = next;
+        port_list_head = next;
       else
-       prev->next = next;
+        prev->next = next;
 
       sfree (pe);
       pe = next;
@@ -433,6 +435,7 @@ static void conn_reset_port_entry (void)
     memset (pe->count_remote, '\0', sizeof (pe->count_remote));
     pe->flags &= ~PORT_IS_LISTENING;
 
+    prev = pe;
     pe = pe->next;
   }
 } /* void conn_reset_port_entry */
@@ -481,6 +484,7 @@ static int conn_handle_ports (uint16_t port_local, uint16_t port_remote, uint8_t
  * zero on other errors. */
 static int conn_read_netlink (void)
 {
+#if HAVE_STRUCT_LINUX_INET_DIAG_REQ
   int fd;
   struct sockaddr_nl nladdr;
   struct nlreq req;
@@ -609,6 +613,9 @@ static int conn_read_netlink (void)
 
   /* Not reached because the while() loop above handles the exit condition. */
   return (0);
+#else
+  return (1);
+#endif /* HAVE_STRUCT_LINUX_INET_DIAG_REQ */
 } /* int conn_read_netlink */
 
 static int conn_handle_line (char *buffer)
@@ -744,7 +751,7 @@ static int conn_config (const char *key, const char *value)
 #if KERNEL_LINUX
 static int conn_init (void)
 {
-  if (port_list_head == NULL)
+  if (port_collect_total == 0 && port_list_head == NULL)
     port_collect_listening = 1;
 
   return (0);
@@ -938,7 +945,9 @@ static int conn_init (void)
 static int conn_read (void)
 {
   struct inpcbtable table;
+#if !defined(__OpenBSD__) && (defined(__NetBSD_Version__) && __NetBSD_Version__ <= 699002700)
   struct inpcb *head;
+#endif
   struct inpcb *next;
   struct inpcb inpcb;
   struct tcpcb tcpcb;
@@ -951,18 +960,32 @@ static int conn_read (void)
   if (status != 0)
     return (-1);
 
+#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
+  /* inpt_queue is a TAILQ on OpenBSD */
+  /* Get the first pcb */
+  next = (struct inpcb *)TAILQ_FIRST (&table.inpt_queue);
+  while (next)
+#else
   /* Get the `head' pcb */
   head = (struct inpcb *) &(inpcbtable_ptr->inpt_queue);
   /* Get the first pcb */
   next = (struct inpcb *)CIRCLEQ_FIRST (&table.inpt_queue);
 
   while (next != head)
+#endif
   {
     /* Read the pcb pointed to by `next' into `inpcb' */
-    kread ((u_long) next, &inpcb, sizeof (inpcb));
+    status = kread ((u_long) next, &inpcb, sizeof (inpcb));
+    if (status != 0)
+      return (-1);
 
     /* Advance `next' */
+#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
+    /* inpt_queue is a TAILQ on OpenBSD */
+    next = (struct inpcb *)TAILQ_NEXT (&inpcb, inp_queue);
+#else
     next = (struct inpcb *)CIRCLEQ_NEXT (&inpcb, inp_queue);
+#endif
 
     /* Ignore sockets, that are not connected. */
 #ifdef __NetBSD__
@@ -977,7 +1000,9 @@ static int conn_read (void)
       continue;
 #endif
 
-    kread ((u_long) inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
+    status = kread ((u_long) inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
+    if (status != 0)
+      return (-1);
     conn_handle_ports (ntohs(inpcb.inp_lport), ntohs(inpcb.inp_fport), tcpcb.t_state);
   } /* while (next != head) */