Merge branch 'collectd-5.4' into collectd-5.5
[collectd.git] / src / iptables.c
index fb887da..590b693 100644 (file)
@@ -1,8 +1,8 @@
 /**
  * collectd - src/iptables.c
- * Copyright (C) 2007 Sjoerd van der Berg
- * Copyright (C) 2007 Florian octo Forster
- * Copyright (C) 2009 Marco Chiappero
+ * Copyright (C) 2007       Sjoerd van der Berg
+ * Copyright (C) 2007-2010  Florian octo Forster
+ * Copyright (C) 2009       Marco Chiappero
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -20,7 +20,7 @@
  *
  * Authors:
  *  Sjoerd van der Berg <harekiet at users.sourceforge.net>
- *  Florian Forster <octo at verplant.org>
+ *  Florian Forster <octo at collectd.org>
  *  Marco Chiappero <marco at absence.it>
  **/
 
 #include "plugin.h"
 #include "configfile.h"
 
-#if OWN_LIBIPTC
-# include "libiptc/libiptc.h"
-# include "libiptc/libip6tc.h"
-#else
-# include <libiptc/libiptc.h>
-# include <libiptc/libip6tc.h>
+#include <sys/socket.h>
+
+#include <libiptc/libiptc.h>
+#include <libiptc/libip6tc.h>
+
+/*
+ * iptc_handle_t was available before libiptc was officially available as a
+ * shared library. Note, that when the shared lib was introduced, the API and
+ * ABI have changed slightly:
+ * 'iptc_handle_t' used to be 'struct iptc_handle *' and most functions used
+ * 'iptc_handle_t *' as an argument. Now, most functions use 'struct
+ * iptc_handle *' (thus removing one level of pointer indirection).
+ *
+ * HAVE_IPTC_HANDLE_T is used to determine which API ought to be used. While
+ * this is somewhat hacky, I didn't find better way to solve that :-/
+ * -tokkee
+ */
+#ifndef HAVE_IPTC_HANDLE_T
+typedef struct iptc_handle iptc_handle_t;
+#endif
+#ifndef HAVE_IP6TC_HANDLE_T
+typedef struct ip6tc_handle ip6tc_handle_t;
 #endif
 
 /*
@@ -89,136 +105,133 @@ static int chain_num = 0;
 static int iptables_config (const char *key, const char *value)
 {
        /* int ip_value; */
-       protocol_version_t ip_version;
+       protocol_version_t ip_version = 0;
 
        if (strcasecmp (key, "Chain") == 0)
                ip_version = IPV4;
        else if (strcasecmp (key, "Chain6") == 0)
                ip_version = IPV6;
+       else
+               return (1);
 
-       if (( ip_version == IPV4 ) || ( ip_version == IPV6 ))
-       {
-               ip_chain_t temp, *final, **list;
-               char *table;
-               int   table_len;
-               char *chain;
-               int   chain_len;
-
-               char *value_copy;
-               char *fields[4];
-               int   fields_num;
-               
-               memset (&temp, 0, sizeof (temp));
-
-               value_copy = strdup (value);
-               if (value_copy == NULL)
-               {
-                   char errbuf[1024];
-                   ERROR ("strdup failed: %s",
-                           sstrerror (errno, errbuf, sizeof (errbuf)));
-                   return (1);
-               }
+       ip_chain_t temp, *final, **list;
+       char *table;
+       int   table_len;
+       char *chain;
+       int   chain_len;
 
-               /*
-                *  Time to fill the temp element
-                *  Examine value string, it should look like:
-                *  Chain[6] <table> <chain> [<comment|num> [name]]
-                        */
+       char *value_copy;
+       char *fields[4];
+       int   fields_num;
 
-               /* set IPv4 or IPv6 */
-                temp.ip_version = ip_version;
+       memset (&temp, 0, sizeof (temp));
 
-               /* Chain <table> <chain> [<comment|num> [name]] */
-               fields_num = strsplit (value_copy, fields, 4);
-               if (fields_num < 2)
-               {
-                   free (value_copy);
-                   return (1);
-               }
+       value_copy = strdup (value);
+       if (value_copy == NULL)
+       {
+           char errbuf[1024];
+           ERROR ("strdup failed: %s",
+                   sstrerror (errno, errbuf, sizeof (errbuf)));
+           return (1);
+       }
 
-               table = fields[0];
-               chain = fields[1];
+       /*
+        *  Time to fill the temp element
+        *  Examine value string, it should look like:
+        *  Chain[6] <table> <chain> [<comment|num> [name]]
+        */
 
-               table_len = strlen (table) + 1;
-               if ((unsigned int)table_len > sizeof(temp.table))
-               {
-                       ERROR ("Table `%s' too long.", table);
-                       free (value_copy);
-                       return (1);
-               }
-               sstrncpy (temp.table, table, table_len);
+       /* set IPv4 or IPv6 */
+       temp.ip_version = ip_version;
 
-               chain_len = strlen (chain) + 1;
-               if ((unsigned int)chain_len > sizeof(temp.chain))
-               {
-                       ERROR ("Chain `%s' too long.", chain);
-                       free (value_copy);
-                       return (1);
-               }
-               sstrncpy (temp.chain, chain, chain_len);
+       /* Chain <table> <chain> [<comment|num> [name]] */
+       fields_num = strsplit (value_copy, fields, 4);
+       if (fields_num < 2)
+       {
+           free (value_copy);
+           return (1);
+       }
 
-               if (fields_num >= 3)
-               {
-                   char *comment = fields[2];
-                   int   rule = atoi (comment);
-
-                   if (rule)
-                   {
-                       temp.rule.num = rule;
-                       temp.rule_type = RTYPE_NUM;
-                   }
-                   else
-                   {
-                       temp.rule.comment = strdup (comment);
-                       if (temp.rule.comment == NULL)
-                       {
-                           free (value_copy);
-                           return (1);
-                       }
-                       temp.rule_type = RTYPE_COMMENT;
-                   }
-               }
-               else
-               {
-                   temp.rule_type = RTYPE_COMMENT_ALL;
-               }
+       table = fields[0];
+       chain = fields[1];
 
-               if (fields_num >= 4)
-                   sstrncpy (temp.name, fields[3], sizeof (temp.name));
+       table_len = strlen (table) + 1;
+       if ((unsigned int)table_len > sizeof(temp.table))
+       {
+               ERROR ("Table `%s' too long.", table);
+               free (value_copy);
+               return (1);
+       }
+       sstrncpy (temp.table, table, table_len);
 
+       chain_len = strlen (chain) + 1;
+       if ((unsigned int)chain_len > sizeof(temp.chain))
+       {
+               ERROR ("Chain `%s' too long.", chain);
                free (value_copy);
-               value_copy = NULL;
-               table = NULL;
-               chain = NULL;
+               return (1);
+       }
+       sstrncpy (temp.chain, chain, chain_len);
 
-               list = (ip_chain_t **) realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
-               if (list == NULL)
+       if (fields_num >= 3)
+       {
+           char *comment = fields[2];
+           int   rule = atoi (comment);
+
+           if (rule)
+           {
+               temp.rule.num = rule;
+               temp.rule_type = RTYPE_NUM;
+           }
+           else
+           {
+               temp.rule.comment = strdup (comment);
+               if (temp.rule.comment == NULL)
                {
-                   char errbuf[1024];
-                   ERROR ("realloc failed: %s",
-                           sstrerror (errno, errbuf, sizeof (errbuf)));
+                   free (value_copy);
                    return (1);
                }
+               temp.rule_type = RTYPE_COMMENT;
+           }
+       }
+       else
+       {
+           temp.rule_type = RTYPE_COMMENT_ALL;
+       }
 
-               chain_list = list;
-               final = (ip_chain_t *) malloc( sizeof(temp) );
-               if (final == NULL) 
-               {
-                   char errbuf[1024];
-                   ERROR ("malloc failed: %s",
-                           sstrerror (errno, errbuf, sizeof (errbuf)));
-                   return (1);
-               }
-               memcpy (final, &temp, sizeof (temp));
-               chain_list[chain_num] = final;
-               chain_num++;
+       if (fields_num >= 4)
+           sstrncpy (temp.name, fields[3], sizeof (temp.name));
+
+       free (value_copy);
+       value_copy = NULL;
+       table = NULL;
+       chain = NULL;
 
-               DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
+       list = (ip_chain_t **) realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
+       if (list == NULL)
+       {
+           char errbuf[1024];
+           ERROR ("realloc failed: %s",
+                   sstrerror (errno, errbuf, sizeof (errbuf)));
+           sfree (temp.rule.comment);
+           return (1);
        }
-       else 
+
+       chain_list = list;
+       final = (ip_chain_t *) malloc( sizeof(temp) );
+       if (final == NULL)
        {
-               return (-1);
+           char errbuf[1024];
+           ERROR ("malloc failed: %s",
+                   sstrerror (errno, errbuf, sizeof (errbuf)));
+           sfree (temp.rule.comment);
+           return (1);
        }
+       memcpy (final, &temp, sizeof (temp));
+       chain_list[chain_num] = final;
+       chain_num++;
+
+       DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
 
        return (0);
 } /* int iptables_config */
@@ -272,11 +285,11 @@ static int submit6_match (const struct ip6t_entry_match *match,
     }
 
     sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
-    values[0].counter = (counter_t) entry->counters.bcnt;
+    values[0].derive = (derive_t) entry->counters.bcnt;
     plugin_dispatch_values (&vl);
 
     sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
-    values[0].counter = (counter_t) entry->counters.pcnt;
+    values[0].derive = (derive_t) entry->counters.pcnt;
     plugin_dispatch_values (&vl);
 
     return (0);
@@ -333,11 +346,11 @@ static int submit_match (const struct ipt_entry_match *match,
     }
 
     sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
-    values[0].counter = (counter_t) entry->counters.bcnt;
+    values[0].derive = (derive_t) entry->counters.bcnt;
     plugin_dispatch_values (&vl);
 
     sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
-    values[0].counter = (counter_t) entry->counters.pcnt;
+    values[0].derive = (derive_t) entry->counters.pcnt;
     plugin_dispatch_values (&vl);
 
     return (0);
@@ -427,8 +440,15 @@ static int iptables_read (void)
 
        if ( chain->ip_version == IPV4 )
         {
-                iptc_handle_t handle;
+#ifdef HAVE_IPTC_HANDLE_T
+               iptc_handle_t _handle;
+               iptc_handle_t *handle = &_handle;
+
+               *handle = iptc_init (chain->table);
+#else
+               iptc_handle_t *handle;
                 handle = iptc_init (chain->table);
+#endif
 
                 if (!handle)
                 {
@@ -438,13 +458,20 @@ static int iptables_read (void)
                         continue;
                 }
 
-                submit_chain (&handle, chain);
-                iptc_free (&handle);
+                submit_chain (handle, chain);
+                iptc_free (handle);
         }
         else if ( chain->ip_version == IPV6 )
         {
-                ip6tc_handle_t handle;
+#ifdef HAVE_IP6TC_HANDLE_T
+               ip6tc_handle_t _handle;
+               ip6tc_handle_t *handle = &_handle;
+
+               *handle = ip6tc_init (chain->table);
+#else
+                ip6tc_handle_t *handle;
                 handle = ip6tc_init (chain->table);
+#endif
 
                 if (!handle)
                 {
@@ -454,8 +481,8 @@ static int iptables_read (void)
                         continue;
                 }
 
-                submit6_chain (&handle, chain);
-                ip6tc_free (&handle);
+                submit6_chain (handle, chain);
+                ip6tc_free (handle);
         }
         else num_failures++;