tcpconns plugin: Add compatibility for OpenBSD.
authorMichael Stapelberg <michael+git@stapelberg.de>
Sat, 9 Aug 2008 12:42:07 +0000 (14:42 +0200)
committerFlorian Forster <octo@noris.net>
Mon, 18 Aug 2008 15:50:00 +0000 (17:50 +0200)
Hi there,

I've just integrated OpenBSD-support into the tcpconns module. Please test this
thouroughly, it's not running for so long on my box (but works fine).

Also, please add -lkvm to the right place in the autoconf-stuff so that when
using tcpconns on OpenBSD, libkvm is linked.

Also, I'm not sure about how much of the license we need to embed. I'll
therefore post the full license information so you can put it in if you feel
like:

/*      $collectd: parts of tcpconns.c, 2008/08/08 03:48:30 Michael Stapelberg $ */
/*      $OpenBSD: inet.c,v 1.100 2007/06/19 05:28:30 ray Exp $  */
/*      $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $        */

/*
 * Copyright (c) 1983, 1988, 1993
 *      The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

Best regards,
Michael

src/tcpconns.c

index 655c53e..b31ebd8 100644 (file)
  *   Florian octo Forster <octo at verplant.org>
  **/
 
+/**
+ * Code within `__OpenBSD__' blocks is provided under the following license:
+ *
+ * $collectd: parts of tcpconns.c, 2008/08/08 03:48:30 Michael Stapelberg $
+ * $OpenBSD: inet.c,v 1.100 2007/06/19 05:28:30 ray Exp $
+ * $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $
+ *
+ * Copyright (c) 1983, 1988, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
 
-#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME
+#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !__OpenBSD__
 # error "No applicable input method."
 #endif
 
 # include <netinet/tcpip.h>
 # include <netinet/tcp_seq.h>
 # include <netinet/tcp_var.h>
-#endif /* HAVE_SYSCTLBYNAME */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif __OpenBSD__
+# include <sys/queue.h>
+# include <sys/socket.h>
+# include <net/route.h>
+# include <netinet/in.h>
+# include <netinet/in_systm.h>
+# include <netinet/ip.h>
+# include <netinet/in_pcb.h>
+# include <netinet/tcp.h>
+# include <netinet/tcp_timer.h>
+# include <netinet/tcp_var.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+# include <nlist.h>
+# include <kvm.h>
+#endif /* __OpenBSD__ */
 
 #if KERNEL_LINUX
 static const char *tcp_state[] =
@@ -100,7 +152,120 @@ static const char *tcp_state[] =
 # define TCP_STATE_LISTEN 1
 # define TCP_STATE_MIN 0
 # define TCP_STATE_MAX 10
-#endif /* HAVE_SYSCTLBYNAME */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif __OpenBSD__
+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"
+};
+
+static kvm_t *kvmd;
+
+static struct nlist nl[] = {
+#define N_MBSTAT        0
+        { "_mbstat" },
+#define N_IPSTAT        1
+        { "_ipstat" },
+#define N_TCBTABLE      2
+        { "_tcbtable" },
+#define N_TCPSTAT       3
+        { "_tcpstat" },
+#define N_UDBTABLE      4
+        { "_udbtable" },
+#define N_UDPSTAT       5
+        { "_udpstat" },
+#define N_IFNET         6
+        { "_ifnet" },
+#define N_ICMPSTAT      7
+        { "_icmpstat" },
+#define N_RTSTAT        8
+        { "_rtstat" },
+#define N_UNIXSW        9
+        { "_unixsw" },
+#define N_RTREE         10
+        { "_rt_tables"},
+#define N_FILE          11
+        { "_file" },
+#define N_IGMPSTAT      12
+        { "_igmpstat" },
+#define N_MRTPROTO      13
+        { "_ip_mrtproto" },
+#define N_MRTSTAT       14
+        { "_mrtstat" },
+#define N_MFCHASHTBL    15
+        { "_mfchashtbl" },
+#define N_MFCHASH       16
+        { "_mfchash" },
+        { "_viftable" },
+#define N_AHSTAT        18
+        { "_ahstat"},
+#define N_ESPSTAT       19
+        { "_espstat"},
+#define N_IP4STAT       20
+        { "_ipipstat"},
+#define N_DDPSTAT       21
+        { "_ddpstat"},
+#define N_DDPCB         22
+        { "_ddpcb"},
+#define N_ETHERIPSTAT   23
+        { "_etheripstat"},
+#define N_IP6STAT       24
+        { "_ip6stat" },
+#define N_ICMP6STAT     25
+        { "_icmp6stat" },
+#define N_PIM6STAT      26
+        { "_pim6stat" },
+#define N_MRT6PROTO     27
+        { "_ip6_mrtproto" },
+#define N_MRT6STAT      28
+        { "_mrt6stat" },
+#define N_MF6CTABLE     29
+        { "_mf6ctable" },
+#define N_MIF6TABLE     30
+        { "_mif6table" },
+#define N_MBPOOL        31
+        { "_mbpool" },
+#define N_MCLPOOL       32
+        { "_mclpool" },
+#define N_IPCOMPSTAT    33
+        { "_ipcompstat" },
+#define N_RIP6STAT      34
+        { "_rip6stat" },
+#define N_CARPSTAT      35
+        { "_carpstats" },
+#define N_RAWIPTABLE    36
+        { "_rawcbtable" },
+#define N_RAWIP6TABLE   37
+        { "_rawin6pcbtable" },
+#define N_PFSYNCSTAT    38
+        { "_pfsyncstats" },
+#define N_PIMSTAT       39
+        { "_pimstat" },
+#define N_AF2RTAFIDX    40
+        { "_af2rtafidx" },
+#define N_RTBLIDMAX     41
+        { "_rtbl_id_max" },
+#define N_RTMASK        42
+        { "_mask_rnhead" },
+
+        { "" }
+};
+
+# define TCP_STATE_LISTEN 1
+# define TCP_STATE_MIN 1
+# define TCP_STATE_MAX 10
+#endif /* __OpenBSD__ */
 
 #define PORT_COLLECT_LOCAL  0x01
 #define PORT_COLLECT_REMOTE 0x02
@@ -514,7 +679,64 @@ static int conn_read (void)
 
   return (0);
 } /* int conn_read */
-#endif /* HAVE_SYSCTLBYNAME */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif __OpenBSD__
+static int kread(u_long addr, void *buf, int size)
+{
+  if (kvm_read(kvmd, addr, buf, size) != size)
+  {
+    ERROR ("tcpconns plugin: %s\n", kvm_geterr(kvmd));
+    return (-1);
+  }
+  return (0);
+}
+
+static int conn_init (void)
+{
+  char buf[_POSIX2_LINE_MAX];
+  if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL)
+  {
+    ERROR("tcpconns plugin: %s", buf);
+    return (-1);
+  }
+  if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0)
+  {
+    ERROR("tcpconns plugin: No namelist.");
+    return (-1);
+  }
+  return (0);
+}
+
+static int conn_read (void)
+{
+  u_long off = nl[2].n_value;
+  struct inpcbtable table;
+  struct inpcb *head, *next, *prev;
+  struct inpcb inpcb;
+  struct tcpcb tcpcb;
+
+  conn_reset_port_entry ();
+
+  kread(off, &table, sizeof(table));
+  prev = head = (struct inpcb *)&CIRCLEQ_FIRST(&((struct inpcbtable *)off)->inpt_queue);
+  next = CIRCLEQ_FIRST(&table.inpt_queue);
+
+  while (next != head) {
+    kread((u_long)next, &inpcb, sizeof(inpcb));
+    prev = next;
+    next = CIRCLEQ_NEXT(&inpcb, inp_queue);
+    if (inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
+      continue;
+    kread((u_long)inpcb.inp_ppcb, &tcpcb, sizeof(tcpcb));
+    conn_handle_ports (ntohs(inpcb.inp_lport), ntohs(inpcb.inp_fport), tcpcb.t_state);
+  }
+
+  conn_submit_all ();
+
+  return (0);
+}
+#endif /* __OpenBSD__ */
 
 void module_register (void)
 {
@@ -522,6 +744,10 @@ void module_register (void)
                        config_keys, config_keys_num);
 #if KERNEL_LINUX
        plugin_register_init ("tcpconns", conn_init);
+#elif HAVE_SYSCTLBYNAME
+       /* no initialization */
+#elif __OpenBSD__
+       plugin_register_init ("tcpconns", conn_init);
 #endif
        plugin_register_read ("tcpconns", conn_read);
 } /* void module_register */