[collectd] [PATCH] Make tcpconns run on OpenBSD

Michael Stapelberg michael at stapelberg.de
Sat Aug 9 14:44:37 CEST 2008


Hi Sebastian,

* [09.08.08 11:06]:
> Thanks for your patch!
You're welcome.

> Which parts of your patch does the licence apply to?
Basically, I ripped this code out of netstat (and cleaned it quite a
bit/stripped it to what we need). So, the BSD license and the copyright I
pasted is for everything in this patch.

> Uh... I can hardly image that you need all of those headers. Also, most
> of them are already included by collectd.h. The ones that are missing
I wrote the plugin as a standalone proof-of-concept before so I needed all of
them then ;-). You are right, I could remove some of them.

> > +kvm_t *kvmd;
> This should be made static.
Yes, I forgot that, sorry.

> > +struct nlist nl[] = {
> > +#define N_MBSTAT        0
> > +        { "_mbstat" },
> [...]
> 
> I don't see you using any of those defines. Is there any reason to keep
> them or could they be removed? Again, the array should be declared
> static.
Well, this was a strange issue. I first tried to use the struct without the
defines, but then it just did not work (getting the memory areas for the
kvm-calls into this list). Maybe there is some evil magic going on in the
OpenBSD's nlist.h internals, I'm not sure. I'd rather keep them.

> Frankly, I'm too lazy to look into the kvm documentation right now.
> Could you please explain in a few words what this array is used for?
Sure. The array will be filled with memory offsets of where the data is which
you want to get. In this case it will be filled with the offset of the list of
TCP connections which is then iterated.

> Right now, this looks like a whole lot of magic to me ;-) Also, it would
> be interesting to know how that array depends on the version of kvm,
> i.e. how likely do we run into problems if people use different versions
> of kvm. Does order matter?
Order definitely matters. As written above, even the defines matter somehow.
I'm not sure about the version of kvm and couldn't find anything about it in
the original netstat code. I think this should be backwards compatible.

> Besides that, the patch looks fine to me from a quick glance and without
> looking into the kvm stuff. If you fix those issues the patch would be
> fine for inclusion from my point of view.
So, I've attached a version with the static variable definition and a bit less
headers.

Best regards,
Michael
-------------- next part --------------
From fabb139ac336d70d737699310f71671b4c0214c7 Mon Sep 17 00:00:00 2001
From: Michael Stapelberg <michael+git at stapelberg.de>
Date: Sat, 9 Aug 2008 14:42:07 +0200
Subject: [PATCH] Make tcpconns work on OpenBSD

---
 src/tcpconns.c |  194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 190 insertions(+), 4 deletions(-)

diff --git a/src/tcpconns.c b/src/tcpconns.c
index 655c53e..c4e12a5 100644
--- a/src/tcpconns.c
+++ b/src/tcpconns.c
@@ -23,7 +23,7 @@
 #include "common.h"
 #include "plugin.h"
 
-#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME
+#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !__OpenBSD__
 # error "No applicable input method."
 #endif
 
@@ -57,7 +57,24 @@
 # 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 +117,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;
+
+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
@@ -440,6 +570,62 @@ static int conn_read (void)
 } /* int conn_read */
 /* #endif KERNEL_LINUX */
 
+#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);
+}
+
 #elif HAVE_SYSCTLBYNAME
 static int conn_read (void)
 {
@@ -520,7 +706,7 @@ void module_register (void)
 {
 	plugin_register_config ("tcpconns", conn_config,
 			config_keys, config_keys_num);
-#if KERNEL_LINUX
+#if KERNEL_LINUX || __OpenBSD__
 	plugin_register_init ("tcpconns", conn_init);
 #endif
 	plugin_register_read ("tcpconns", conn_read);
-- 
1.5.2.4

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://mailman.verplant.org/pipermail/collectd/attachments/20080809/a36de7a4/attachment.pgp 


More information about the collectd mailing list