]> zub.fei.tuke.sk Git - fwcnt/commitdiff
Initial commit
authorPeter Popovec <popovec@fei.tuke.sk>
Thu, 22 Feb 2007 13:25:29 +0000 (14:25 +0100)
committerPeter Popovec <popovec@vku-linux.fei.tuke.sk>
Thu, 22 Feb 2007 13:25:29 +0000 (14:25 +0100)
18 files changed:
FWcnt2rrd [new file with mode: 0755]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
README.old [new file with mode: 0644]
TODO [new file with mode: 0644]
clean_FWcnt [new file with mode: 0755]
cnt2rrd.c [new file with mode: 0644]
cron.d [new file with mode: 0644]
fw2rrd [new file with mode: 0755]
fw2rrd.c [new file with mode: 0644]
generate [new file with mode: 0755]
get_FWcnt [new file with mode: 0755]
init_FWcnt [new file with mode: 0755]
wrapper/w0.cgi [new file with mode: 0755]
wrapper/w1.cgi [new file with mode: 0755]
wrapper/w2.cgi [new file with mode: 0755]
wrapper/w3.cgi [new file with mode: 0755]
wrapper/w4.cgi [new file with mode: 0755]

diff --git a/FWcnt2rrd b/FWcnt2rrd
new file mode 100755 (executable)
index 0000000..06a940d
--- /dev/null
+++ b/FWcnt2rrd
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+/usr/lib/FWcnt/fw2rrd
+
+awk 'BEGIN{
+ while(getline <"/proc/net/dev"){
+   if(2==split($0,X,":")){
+       split(X[1],xx," ")
+       eth[xx[1]]=X[2]
+   }
+ }
+}
+{
+ if($1 == "cntLINK"){
+  if($2 in eth){
+       split(eth[$2],data)
+       C="test -f "$2"-p.rrd||rrdtool create "$2"-p.rrd  --step 300 DS:ds0:DERIVE:600:0:U DS:ds1:DERIVE:600:0:U RRA:AVERAGE:0.5:1:800 RRA:AVERAGE:0.5:6:800 RRA:AVERAGE:0.5:24:800 RRA:AVERAGE:0.5:288:800 RRA:MAX:0.5:1:800 RRA:MAX:0.5:6:800 RRA:MAX:0.5:24:800 RRA:MAX:0.5:288:800"
+       system(C)
+       close(C)
+       C="test -f "$2"-b.rrd||rrdtool create "$2"-b.rrd  --step 300 DS:ds0:DERIVE:600:0:U DS:ds1:DERIVE:600:0:U RRA:AVERAGE:0.5:1:800 RRA:AVERAGE:0.5:6:800 RRA:AVERAGE:0.5:24:800 RRA:AVERAGE:0.5:288:800 RRA:MAX:0.5:1:800 RRA:MAX:0.5:6:800 RRA:MAX:0.5:24:800 RRA:MAX:0.5:288:800"
+       system(C)
+       close(C)
+       C="rrdtool update "$2"-b.rrd N:"data[1]":"data[9]
+       system(C)
+       close(C)
+       C="rrdtool update "$2"-p.rrd N:"data[2]":"data[10]
+       system(C)
+       close(C)
+  }
+ }
+}' /var/lib/FWcnt/etc/config 2>/dev/null
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..7b45f2d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+fw2rrd:        fw2rrd.c 
+       cc fw2rrd.c -Wall -Wshadow -Wbad-function-cast \
+       -pedantic -Wno-long-long  -Wstrict-prototypes \
+       -o fw2rrd -lrrd -O2
+
+install:       fw2rrd
+               mkdir                /usr/lib/FWcnt;true
+               cp fw2rrd            /usr/lib/FWcnt/
+               cp init_FWcnt        /usr/lib/FWcnt/
+               cp clean_FWcnt       /usr/lib/FWcnt/
+               cp get_FWcnt         /usr/lib/FWcnt/
+               cp generate          /usr/lib/FWcnt/
+               cp FWcnt2rrd         /usr/lib/FWcnt/
+               mkdir                /var/www/mrtg-rrd;true
+               chown www-data       /var/www/mrtg-rrd
+               mkdir                /var/lib/FWcnt;true
+               mkdir                /var/lib/FWcnt/etc;true
+               mkdir                /var/lib/FWcnt/FW_rrd_database;true
+               mkdir                /var/lib/FWcnt/run_conf;true
+               touch                /var/lib/FWcnt/etc/config
+               chown Debian-ippl -R /var/lib/FWcnt/FW_rrd_database             
+               cp cron.d            /etc/cron.d/FWcnt          
+               cat mrtg-rrd.wrapper.cgi >/usr/lib/cgi-bin/mrtg-rrd.wrapper.cgi
+
+depends:
+               dpkg -l gawk mrtg-rrd ippl mrtg iptables cron bash librrd2-dev
+
+clean:
+               rm -f fw2rrd
+               
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..1dc77f3
--- /dev/null
+++ b/README
@@ -0,0 +1,279 @@
+Version 0.3pre1 
+---------------
+
+Detailed measuring system for wide range of IPs
+-----------------------------------------------
+
+"fast" setup
+------------
+
+1. copy this sample in /var/lib/FWcnt/etc/config (replace 192.168.0.0 with your
+IP)
+---------------- cut ----------------
+cntLINK eth0
+cntNET 192.168.0.0
+---------------- cut ----------------
+
+2. run /usr/lib/FWcnt/init_FWcnt
+
+3. run /usr/lib/FWcnt/generate
+
+4. show http://YOUR_WEB/cgi-bin/mrtg-rrd.wrapper.cgi
+
+
+
+
+Part 1:
+*******
+
+Kernel counters in iptables is used for counting paket and byte count od
+each measurments.
+
+Specification & features
+-------------------------
+
+1. each IP has own In and Out counter
+2. each subnet of 8,16,32,64,128,256 IP has own In and Out counter
+3. paket traverse only minimum rules in firewall
+   max rules = 1(C range)+2(Ip/25)+4(Ip/26)+8(Ip/27)+
+       16(subchains = Ip/28)+2(Ip/29)+16 = 49 rules one direction
+   For reverse direction one more rule must be added. 
+   Full C bidirectional counting is counted by max 50 rules
+   For each C class  one rule more must be traversed for one direction
+   
+   
+for each C range exists this structure:
+
+match 
+full ---+ rule subnet 0-127
+C       + rule subnet 128-255
+range   + rule subnet 0 - 63
+        + rule subnet 64-127
+        + rule subnet 128-191
+       + rule subnet 192-255
+        + rule subnet 0-31
+        + rule subnet 32-63
+        + .
+       + .
+       + rule subnet 224-255
+        + subchain         0-15   ----+ rule subnet 0-7
+        |                             + rule subnet 8-15
+       |                             + rule 0
+       |                             + rule 1
+       |                             + .
+        |                             + .
+        |                             + rule 15
+        + subchain        16-32   ----+ rule subnet 16-23
+        |                             + rule subnet 24-31
+       |                             + rule 16
+       |                             + rule 17
+       |                             + .
+        |                             + .
+        |                             + rule 31
+        .
+        .
+        + subchain        240-255 ----+ rule subnet 240-247
+                                      + rule subnet 248-255
+                                     + rule 240
+                                     + rule 241
+                                     + .
+                                      + .
+                                      + rule 255
+
+
+                                               
+Chain FWcnt is managed by programs init_FWcnt, get_FWcnt and clean_FWcnt.
+
+clean_FWcnt erase all rules and subchains in FWcnt chain
+get_FWcnt   read counters from rules in FWcnt chain
+init_FWcnt  set up rules for one C ranges of IPs for measurments
+
+Example: to set up measurments for one C range 192.168.0.0
+
+init_FWcnt 192.168.0
+
+Without argumet this command read configuration file and set up counters for
+all nets defined by keywork "cntNET" in config file (see below).
+
+
+Initialization in FW:
+
+iptables -N FWcnt              #base chain for measurments
+iptables -I INPUT -j FWcnt     #count input
+iptables -I OUTPUT -j FWcnt    #count output
+iptables -I FORWARD -j FWcnt   #count forward
+
+
+getting counters:
+
+get_FWcnt
+
+return 4 values per line .. paket count, bytes count, source IP destination IP 
+
+
+Part 2
+******
+
+counter database
+----------------
+
+Text database used by mrtg is slow. RRD database is used for each counter
+rule. 
+
+cron job read all counters in FWcnt chain by calling "get_FWcnt".
+Output of "get_FWcnt" is passed to binary fw2rrd (from source fw2rrd.c)
+For each counter from FWcnt chain reverse counter is searched. If database
+file does not exist, then fw2rrd create one for each counter. fw2rrd must be
+running in working directory. Only iptables command must run with root
+privileges, database can be run by different user.
+
+example cron job:
+
+
+0-55/5 *       * * * root if [ -x /usr/lib/FWcnt/get_FWcnt ]; then  \
+   (env LANG=C /usr/lib/FWcnt/get_FWcnt |su --shell=/bin/bash \
+   -c '(cd /var/lib/FWcnt/FW_rrd_database/; \
+   /usr/lib/FWcnt/fw2rrd' Debian-ippl);fi
+
+
+Counter name is derived vrom IP number.
+For each counter pair exists two rrd files, one for bytes count and one for 
+pakets count. Name convencion: 
+
+IP1.IP2.IP3.IP4_NM-b.rrd       bytes for net IP1.IP2.IP3.IP4_NM
+IP1.IP2.IP3.IP4_NM-p.rrd       pakets for net IP1.IP2.IP3.IP4_NM
+
+IP1..IP4  number 0..255
+NM netmask bits (0 ..32) 
+-p.rrd fixed part of name for pakets counter
+-b.rrd fixed part of name for bytes counter
+
+"Target" name of counter is filename without .rrd suffix
+
+Warning,  "_NM" is optional, for measuring one IP "_NM" can be "_32" or this
+part of name absent.
+
+example:
+
+192.168.0.1-b.rrd      byte counter for one IP  192.168.0.1
+192.168.0.1_32-b.rrd    byte counter for one IP  192.168.0.1 but !!WARNING!!
+                       this counters is different from previous
+
+192.168.0.0_16-p.rrd    pakets counter for "B" class net 192.168.0.0 
+
+
+
+Part3
+*****
+
+ethernet device measurment
+--------------------------
+
+data for each ethernet device can be found in /proc/net/dev. Not all devices
+is "counted". Only devices found in config file is used for measurment.
+
+FWcnt2rrd  first run fw2rrd, next  check configuration file and for each
+device  create/update counter file. 
+
+example config file (onli  part for devices)
+--------------- cut --------------
+cntLINK eth0
+cntLINK vlan2
+--------------- cut --------------
+
+counter files with names:
+eth0-p.rrd
+eth0-b.rrd
+vlan2-p.rrd
+vlan2-b.rrd
+
+
+
+
+Visualization of counters by mrtg.
+----------------------------------
+
+mrtg-rrd is used to visualize rrd files. Original mrtg-rrd does not use
+multiple config files, wrapper is created for  adapt mrtg-rrd to count C
+class networks.
+
+All needed config files for mrtg-rrd is automaticali generated by 
+"generate" command.
+
+"generate" first creates one page with graphs for ethernet devices (based on
+config file) and next graph for summary  of one C class. 
+
+below graph for C class is subsummary graphs for /28 subnets (default) or
+subnets of C class defined in config file by directive "mrtgNET". 
+Both variant of netmask can be used. 
+
+Example config:
+
+---------------------------- cut -------------------------
+#eth interfaces 
+cntLINK eth2
+cntLINK eth0
+# firewall counters for C class nets
+cntNET 192.168.40
+cntNET 192.168.42.0
+#
+mrtgNET 192.168.40.0 24 
+mrtgNET 192.168.42.0 25 
+mrtgNET 192.168.42.128 28 
+mrtgNET 192.168.42.144 29 
+mrtgNET 192.168.42.152 29 
+mrtgNET 192.168.42.160 27 
+mrtgNET 192.168.42.195 255.255.255.192
+---------------------------- cut -------------------------
+
+
+Keywork "cntNET" is used for definition of counter for "init_FWcnt" command. 
+
+
+
+
+
+
+
+
+
+
+
+
+obsollete files from previous development. 
+------------------------------------------
+cnt2rrd [filename]
+
+read filename or stdin if no filename is specified. Format of input file is
+designed for iptables -L output but target must be RETURN.
+Example input file:
+
+----------------------- cut ---------------------------
+Chain CNTin (1 references)
+    pkts      bytes target     prot opt in     out     source destination
+  302978 50655932 RETURN     all  --  *      *       0.0.0.0/0 62.168.101.165
+Chain CNTout (1 references)
+    pkts      bytes target     prot opt in     out     source destination
+       2      211 RETURN     all  --  *      *       62.168.101.165 0.0.0.0/0
+
+----------------------- cut ---------------------------
+
+
+more chains can be concatenated in input and chains may consist of couple of
+rules for input and output. As "download" must be source set to
+0.0.0.0/0. for upload must be destination set to 0.0.0.0/0. Protocol must be
+"all", opt must be "--" and in and out must be "-".
+
+For each couple of rule (one for down and one for upload) two rrd files are
+updated. Name od rrd file is derived from IP (or ip and netmask). For IP
+62.168.101.165 for example  is output rrd filename 62.168.101.165a.rrd and
+62.168.101.165b.rrd. First file is updated by bytes counters from chain and
+seconf from pakets counter. 
+
+If IP if rule match subnet (etc 172.26.0.0/24) file is named
+172.26.0.0_24a.rrd (all "/" is replaced by "_").
+
+Special IP ranges etc may cause problems.. 
+
+WARNING ! rrd files creation is done in working directory. 
+
diff --git a/README.old b/README.old
new file mode 100644 (file)
index 0000000..3e087bd
--- /dev/null
@@ -0,0 +1,68 @@
+cnt2rrd [filename]
+
+read filename or stdin if no filename is specified. Format of input file is
+designed for iptables -L output but target must be RETURN.
+Example input file:
+
+----------------------- cut ---------------------------
+Chain CNTin (1 references)
+    pkts      bytes target     prot opt in     out     source destination
+  302978 50655932 RETURN     all  --  *      *       0.0.0.0/0 62.168.101.165
+Chain CNTout (1 references)
+    pkts      bytes target     prot opt in     out     source destination
+       2      211 RETURN     all  --  *      *       62.168.101.165 0.0.0.0/0
+
+----------------------- cut ---------------------------
+
+
+more chains can be concatenated in input and chains may consist of couple of
+rules for input and output. As "download" must be source set to
+0.0.0.0/0. for upload must be destination set to 0.0.0.0/0. Protocol must be
+"all", opt must be "--" and in and out must be "-".
+
+For each couple of rule (one for down and one for upload) two rrd files are
+updated. Name od rrd file is derived from IP (or ip and netmask). For IP
+62.168.101.165 for example  is output rrd filename 62.168.101.165a.rrd and
+62.168.101.165b.rrd. First file is updated by bytes counters from chain and
+seconf from pakets counter. 
+
+If IP if rule match subnet (etc 172.26.0.0/24) file is named
+172.26.0.0_24a.rrd (all "/" is replaced by "_").
+
+Special IP ranges etc may cause problems.. 
+
+WARNING ! rrd files creation is done in working directory. 
+
+
+
+directory structure:
+
+$ ls -lRa /var/lib/cnt-mrtg/
+/var/lib/cnt-mrtg/:
+total 16
+drwxr-xr-x   4 root      root     4096 May 11 13:56 .
+drwxr-xr-x  30 root      root     4096 May 11 13:55 ..
+drwxr-xr-x   2 root      root     4096 May 11 13:53 bin
+drwxr-xr-x   2 arpwatch www-data 4096 May 11 13:56 rrd-database
+
+/var/lib/cnt-mrtg/bin:
+total 16
+drwxr-xr-x  2 root root 4096 May 11 13:53 .
+drwxr-xr-x  4 root root 4096 May 11 13:56 ..
+-rwxr-xr-x  1 root root 7408 May 11 13:53 cnt2rrd
+
+/var/lib/cnt-mrtg/rrd-database:
+total 8
+drwxr-xr-x  2 arpwatch www-data 4096 May 11 13:56 .
+drwxr-xr-x  4 root      root     4096 May 11 13:56 ..
+
+$ ls -lRa /var/log/cnt-mrtg/
+/var/log/cnt-mrtg/:
+total 8
+drwxr-xr-x   2 arpwatch adm  4096 May 11 13:58 .
+drwxr-xr-x  12 root      root 4096 May 11 13:58 ..
+
+
+
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..150d474
--- /dev/null
+++ b/TODO
@@ -0,0 +1,3 @@
+* get name for IP/net
+
+* iptables counter setting (start/stop) from /etc/network/intrfaces
diff --git a/clean_FWcnt b/clean_FWcnt
new file mode 100755 (executable)
index 0000000..c39c657
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+for i in `iptables -L FWcnt -n|awk '{if($0 ~ "^FWcnt"){if(NR>2)print $1}}';iptables -F FWcnt` ;do
+ for j in `iptables -L ${i} -n |awk '{if($0 ~ "^FWcnt"){if(NR>2)print $1}}';iptables -F ${i}` ;do 
+  iptables -F ${j}
+  iptables -X ${j}
+ done
+ iptables -X ${i}
+done
+
diff --git a/cnt2rrd.c b/cnt2rrd.c
new file mode 100644 (file)
index 0000000..6b15a2f
--- /dev/null
+++ b/cnt2rrd.c
@@ -0,0 +1,309 @@
+/* for version of rrdtool before 2005-05-01 10:23 must be 
+optind initioalized before callinf any of rrd_*. 
+Please uncoment #define DO_GETOPT_RESET for old version of rrd 
+or comment out for new versions
+*/
+#define DO_GETOPT_RESET
+#define _GNU_SOURCE
+
+#define IPLIMIT 20
+#define HASHMAX 100
+#define BUFF_SIZE 2000
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <rrd.h>
+#ifdef DO_GETOPT_RESET
+#include <unistd.h>
+#endif
+
+/* create new array */
+int
+newRRD (char *name)
+{
+  char *timebuff;
+  char *r_create[] = {
+    "create",
+    NULL,
+    "--start",
+    NULL,
+    "--step",
+    "300",
+    "DS:ds0:DERIVE:600:0:U",
+    "DS:ds1:DERIVE:600:0:U",
+    "RRA:AVERAGE:0.5:1:800",
+    "RRA:AVERAGE:0.5:6:800",
+    "RRA:AVERAGE:0.5:24:800",
+    "RRA:AVERAGE:0.5:288:800",
+    "RRA:MAX:0.5:1:800",
+    "RRA:MAX:0.5:6:800",
+    "RRA:MAX:0.5:24:800",
+    "RRA:MAX:0.5:288:800"
+  };
+  asprintf (&timebuff, "%ld", time (NULL) - 10);
+  r_create[1] = name;
+  r_create[3] = timebuff;
+
+#ifdef DO_GETOPT_RESET
+  optind = 0;
+  opterr = 0;
+#endif
+  rrd_create (16, r_create);
+  if (rrd_test_error ())
+    {
+      fprintf (stderr, "Unable to create %s,%s\n", name, rrd_get_error ());
+      rrd_clear_error ();
+      return (1);
+    }
+  free (timebuff);
+  return (0);
+}
+
+
+
+
+int
+updateRRD (char *key, unsigned long long inPkts, unsigned long long outPkts,
+          unsigned long long inBytes, unsigned long long outBytes)
+{
+  FILE *rrdfile;
+  char *r_buf, *name;
+  int i;
+  char *r_update[3] = { "update", NULL, NULL };
+
+  asprintf (&name, "%sa.rrd", key);
+  i = strlen (name);
+  while (i > 0)
+    {
+      if (name[i] == '/')
+       name[i] = '_';
+      i--;
+    }
+  if (NULL == (rrdfile = fopen (name, "r")))
+    newRRD (name);
+  else
+    fclose (rrdfile);
+  asprintf (&r_buf, "N:%lld:%lld", inBytes, outBytes);
+  r_update[1] = name;
+  r_update[2] = r_buf;
+#ifdef DO_GETOPT_RESET
+  optind = 0;
+  opterr = 0;
+#endif
+  rrd_update (3, r_update);
+  if (rrd_test_error ())
+    {
+      fprintf (stderr, "Unable to update %s\n", name);
+      rrd_clear_error ();
+    }
+  free (r_buf);
+  free (name);
+  asprintf (&name, "%sb.rrd", key);
+  i = strlen (name);
+  while (i > 0)
+    {
+      if (name[i] == '/')
+       name[i] = '_';
+      i--;
+    }
+  if (NULL == (rrdfile = fopen (name, "r")))
+    newRRD (name);
+  else
+    fclose (rrdfile);
+  asprintf (&r_buf, "N:%lld:%lld", inPkts, outPkts);
+  r_update[1] = name;
+  r_update[2] = r_buf;
+#ifdef DO_GETOPT_RESET
+  optind = 0;
+  opterr = 0;
+#endif
+  rrd_update (3, r_update);
+  if (rrd_test_error ())
+    {
+      fprintf (stderr, "Unable to update %s\n", name);
+      rrd_clear_error ();
+    }
+  free (r_buf);
+  free (name);
+  return (0);
+}
+
+
+
+struct CNT
+{
+  char *key;
+  unsigned long long inBytes;
+  unsigned long long outBytes;
+  unsigned long long inPkts;
+  unsigned long long outPkts;
+  int count;
+  struct CNT *next;
+};
+
+struct CNT *CNThash[HASHMAX];
+int
+add_to_hash (unsigned int h, char *key, unsigned long long bytes,
+            unsigned long long pakets, int direction)
+{
+  struct CNT *newCNT, *actual;
+  int hash;
+  hash = h % HASHMAX;
+  actual = CNThash[hash];
+  while (actual != NULL)       /* search */
+    {
+      if (0 == strcmp (key, actual->key))      /* found */
+       {
+         if (direction == 1)
+           {
+             actual->inBytes = bytes;
+             actual->inPkts = pakets;
+           }
+         else
+           {
+             actual->outBytes = bytes;
+             actual->outPkts = pakets;
+           }
+         if (actual->count == 1)
+           updateRRD (actual->key, actual->inPkts, actual->outPkts,
+                      actual->inBytes, actual->outBytes);
+         else
+           {
+             fprintf (stderr, "Warning: count for key %s = %d\n",
+                      actual->key, actual->count);
+             (actual->count)++;
+           }
+
+         return (0);           /* key found, do return */
+       }
+      actual = actual->next;
+    }
+  if (NULL == (newCNT = malloc (sizeof (struct CNT))))
+    {
+      fprintf (stderr, "Error, unable to alocate memory\n");
+      exit (2);
+    }
+  newCNT->key = strdup (key);
+  if (direction == 1)
+    {
+      newCNT->inBytes = bytes;
+      newCNT->inPkts = pakets;
+      newCNT->outBytes = 0;
+      newCNT->outPkts = 0;
+    }
+  else
+    {
+      newCNT->outBytes = bytes;
+      newCNT->outPkts = pakets;
+      newCNT->inBytes = 0;
+      newCNT->inPkts = 0;
+    }
+  newCNT->count = 1;
+  newCNT->next = CNThash[hash];
+  CNThash[hash] = newCNT;
+  return (0);
+}
+
+
+
+int
+main (int argc, char **argv)
+{
+  FILE *data;
+  int i, j;
+  unsigned int h;
+  char buffer[BUFF_SIZE], *ptr, ipbuff[IPLIMIT];
+  unsigned long long tmppakets, tmpbytes;
+
+  for (i = 0; i < HASHMAX; i++)
+    CNThash[i] = NULL;
+
+  if (argc == 2)
+    {
+      if (NULL == (data = fopen (argv[1], "r")))
+       {
+         fprintf (stderr, "Unable to open input file\n");
+         return (1);
+       }
+    }
+  else
+    data = stdin;
+
+  while (fgets (buffer, BUFF_SIZE - 1, data))
+    {
+      ptr = buffer;
+      tmppakets = strtoull (ptr, &ptr, 10);
+      tmpbytes = strtoull (ptr, &ptr, 10);
+/* skip RETURN */
+      while (*ptr == ' ')
+       ptr++;
+      if (0 != memcmp (ptr, "RETURN", 6))
+       continue;
+      ptr += 6;
+/* skip all */
+      while (*ptr == ' ')
+       ptr++;
+      if (0 != memcmp (ptr, "all", 3))
+       continue;
+      ptr += 3;
+/* skip -- */
+      while (*ptr == ' ')
+       ptr++;
+      if (*ptr != '-')
+       continue;
+      ptr++;
+      if (*ptr != '-')
+       continue;
+      ptr++;
+/*skip * */
+      while (*ptr == ' ')
+       ptr++;
+      if (*ptr != '*')
+       continue;
+      ptr++;
+/*skip * */
+      while (*ptr == ' ')
+       ptr++;
+      if (*ptr != '*')
+       continue;
+      ptr++;
+/*find IP */
+      while (*ptr == ' ')
+       ptr++;
+      if (0 == memcmp (ptr, "0.0.0.0/0", 9))   /* download */
+       {
+         /* skip IP */
+         while (*ptr == ' ')
+           ptr++;
+         while (*ptr != ' ')
+           ptr++;
+         while (*ptr == ' ')
+           ptr++;
+         for (h = 0, i = 0, j = 0;
+              i < (IPLIMIT - 1) && *ptr != ' ' && *ptr != '\n'; i++, ptr++)
+           {
+             h *= 10;          /* hash key */
+             h += *ptr - '0';
+             ipbuff[i] = *ptr;
+           }
+         ipbuff[i] = 0;
+         add_to_hash (h, ipbuff, tmpbytes, tmppakets, 1);
+       }
+      else
+       {
+         for (h = 0, i = 0, j = 0;
+              i < (IPLIMIT - 1) && *ptr != ' ' && *ptr != '\n'; i++, ptr++)
+           {
+             h *= 10;          /* hash key */
+             h += *ptr - '0';
+             ipbuff[i] = *ptr;
+           }
+         ipbuff[i] = 0;
+         add_to_hash (h, ipbuff, tmpbytes, tmppakets, 0);
+       }
+    }
+  if (data != stdin)
+    fclose (data);
+  return (0);
+}
diff --git a/cron.d b/cron.d
new file mode 100644 (file)
index 0000000..9518d65
--- /dev/null
+++ b/cron.d
@@ -0,0 +1 @@
+0-55/5 *       * * * root if [ -x /usr/lib/FWcnt/get_FWcnt ]; then  (env LANG=C /usr/lib/FWcnt/get_FWcnt |su --shell=/bin/bash -c '(cd /var/lib/FWcnt/FW_rrd_database/;/usr/lib/FWcnt/FWcnt2rrd)' Debian-ippl);fi
diff --git a/fw2rrd b/fw2rrd
new file mode 100755 (executable)
index 0000000..0938d6c
Binary files /dev/null and b/fw2rrd differ
diff --git a/fw2rrd.c b/fw2rrd.c
new file mode 100644 (file)
index 0000000..bf99910
--- /dev/null
+++ b/fw2rrd.c
@@ -0,0 +1,276 @@
+/* for version of rrdtool before 2005-05-01 10:23 must be 
+optind initioalized before callinf any of rrd_*. 
+Please uncoment #define DO_GETOPT_RESET for old version of rrd 
+or comment out for new versions
+*/
+#define DO_GETOPT_RESET
+#define _GNU_SOURCE
+
+#define IPLIMIT 20
+#define HASHMAX 100
+#define BUFF_SIZE 2000
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <rrd.h>
+#ifdef DO_GETOPT_RESET
+#include <unistd.h>
+#endif
+
+/* create new array */
+int
+newRRD (char *name)
+{
+  char *timebuff;
+  char *r_create[] = {
+    "create",
+    NULL,
+    "--start",
+    NULL,
+    "--step",
+    "300",
+    "DS:ds0:DERIVE:600:0:U",
+    "DS:ds1:DERIVE:600:0:U",
+    "RRA:AVERAGE:0.5:1:800",
+    "RRA:AVERAGE:0.5:6:800",
+    "RRA:AVERAGE:0.5:24:800",
+    "RRA:AVERAGE:0.5:288:800",
+    "RRA:MAX:0.5:1:800",
+    "RRA:MAX:0.5:6:800",
+    "RRA:MAX:0.5:24:800",
+    "RRA:MAX:0.5:288:800"
+  };
+  asprintf (&timebuff, "%ld", time (NULL) - 10);
+  r_create[1] = name;
+  r_create[3] = timebuff;
+
+#ifdef DO_GETOPT_RESET
+  optind = 0;
+  opterr = 0;
+#endif
+  rrd_create (16, r_create);
+  if (rrd_test_error ())
+    {
+      fprintf (stderr, "Unable to create %s,%s\n", name, rrd_get_error ());
+      rrd_clear_error ();
+      return (1);
+    }
+  free (timebuff);
+  return (0);
+}
+
+
+
+
+int
+updateRRD (char *key, unsigned long long inPkts, unsigned long long outPkts,
+          unsigned long long inBytes, unsigned long long outBytes)
+{
+  FILE *rrdfile;
+  char *r_buf, *name;
+  int i;
+  char *r_update[3] = { "update", NULL, NULL };
+
+  asprintf (&name, "%s-b.rrd", key);
+  i = strlen (name);
+  while (i > 0)
+    {
+      if (name[i] == '/')
+       name[i] = '_';
+      i--;
+    }
+  if (NULL == (rrdfile = fopen (name, "r")))
+    newRRD (name);
+  else
+    fclose (rrdfile);
+  asprintf (&r_buf, "N:%lld:%lld", inBytes, outBytes);
+  r_update[1] = name;
+  r_update[2] = r_buf;
+#ifdef DO_GETOPT_RESET
+  optind = 0;
+  opterr = 0;
+#endif
+  rrd_update (3, r_update);
+  if (rrd_test_error ())
+    {
+      fprintf (stderr, "Unable to update %s\n", name);
+      rrd_clear_error ();
+    }
+  free (r_buf);
+  free (name);
+  asprintf (&name, "%s-p.rrd", key);
+  i = strlen (name);
+  while (i > 0)
+    {
+      if (name[i] == '/')
+       name[i] = '_';
+      i--;
+    }
+  if (NULL == (rrdfile = fopen (name, "r")))
+    newRRD (name);
+  else
+    fclose (rrdfile);
+  asprintf (&r_buf, "N:%lld:%lld", inPkts, outPkts);
+  r_update[1] = name;
+  r_update[2] = r_buf;
+#ifdef DO_GETOPT_RESET
+  optind = 0;
+  opterr = 0;
+#endif
+  rrd_update (3, r_update);
+  if (rrd_test_error ())
+    {
+      fprintf (stderr, "Unable to update %s\n", name);
+      rrd_clear_error ();
+    }
+  free (r_buf);
+  free (name);
+  return (0);
+}
+
+
+
+struct CNT
+{
+  char *key;
+  unsigned long long inBytes;
+  unsigned long long outBytes;
+  unsigned long long inPkts;
+  unsigned long long outPkts;
+  int count;
+  struct CNT *next;
+};
+
+struct CNT *CNThash[HASHMAX];
+int
+add_to_hash (unsigned int h, char *key, unsigned long long bytes,
+            unsigned long long pakets, int direction)
+{
+  struct CNT *newCNT, *actual;
+  int hash;
+  hash = h % HASHMAX;
+  actual = CNThash[hash];
+  while (actual != NULL)       /* search */
+    {
+      if (0 == strcmp (key, actual->key))      /* found */
+       {
+         if (direction == 1)
+           {
+             actual->inBytes = bytes;
+             actual->inPkts = pakets;
+           }
+         else
+           {
+             actual->outBytes = bytes;
+             actual->outPkts = pakets;
+           }
+         if (actual->count == 1)
+           updateRRD (actual->key, actual->inPkts, actual->outPkts,
+                      actual->inBytes, actual->outBytes);
+         else
+           {
+             fprintf (stderr, "Warning: count for key %s = %d\n",
+                      actual->key, actual->count);
+             (actual->count)++;
+           }
+
+         return (0);           /* key found, do return */
+       }
+      actual = actual->next;
+    }
+  if (NULL == (newCNT = malloc (sizeof (struct CNT))))
+    {
+      fprintf (stderr, "Error, unable to alocate memory\n");
+      exit (2);
+    }
+  newCNT->key = strdup (key);
+  if (direction == 1)
+    {
+      newCNT->inBytes = bytes;
+      newCNT->inPkts = pakets;
+      newCNT->outBytes = 0;
+      newCNT->outPkts = 0;
+    }
+  else
+    {
+      newCNT->outBytes = bytes;
+      newCNT->outPkts = pakets;
+      newCNT->inBytes = 0;
+      newCNT->inPkts = 0;
+    }
+  newCNT->count = 1;
+  newCNT->next = CNThash[hash];
+  CNThash[hash] = newCNT;
+  return (0);
+}
+
+
+
+int
+main (int argc, char **argv)
+{
+  FILE *data;
+  int i, j;
+  unsigned int h;
+  char buffer[BUFF_SIZE], *ptr, ipbuff[IPLIMIT];
+  unsigned long long tmppakets, tmpbytes;
+
+  for (i = 0; i < HASHMAX; i++)
+    CNThash[i] = NULL;
+
+  if (argc == 2)
+    {
+      if (NULL == (data = fopen (argv[1], "r")))
+       {
+         fprintf (stderr, "Unable to open input file\n");
+         return (1);
+       }
+    }
+  else
+    data = stdin;
+
+  while (fgets (buffer, BUFF_SIZE - 1, data))
+    {
+      ptr = buffer;
+      tmppakets = strtoull (ptr, &ptr, 10);
+      tmpbytes = strtoull (ptr, &ptr, 10);
+/*find IP */
+      while (*ptr == ' ')
+       ptr++;
+      if (0 == memcmp (ptr, "0.0.0.0/0", 9))   /* download */
+       {
+         /* skip IP */
+         while (*ptr == ' ')
+           ptr++;
+         while (*ptr != ' ')
+           ptr++;
+         while (*ptr == ' ')
+           ptr++;
+         for (h = 0, i = 0, j = 0;
+              i < (IPLIMIT - 1) && *ptr != ' ' && *ptr != '\n'; i++, ptr++)
+           {
+             h *= 10;          /* hash key */
+             h += *ptr - '0';
+             ipbuff[i] = *ptr;
+           }
+         ipbuff[i] = 0;
+         add_to_hash (h, ipbuff, tmpbytes, tmppakets, 1);
+       }
+      else
+       {
+         for (h = 0, i = 0, j = 0;
+              i < (IPLIMIT - 1) && *ptr != ' ' && *ptr != '\n'; i++, ptr++)
+           {
+             h *= 10;          /* hash key */
+             h += *ptr - '0';
+             ipbuff[i] = *ptr;
+           }
+         ipbuff[i] = 0;
+         add_to_hash (h, ipbuff, tmpbytes, tmppakets, 0);
+       }
+    }
+  if (data != stdin)
+    fclose (data);
+  return (0);
+}
diff --git a/generate b/generate
new file mode 100755 (executable)
index 0000000..3fb1181
--- /dev/null
+++ b/generate
@@ -0,0 +1,119 @@
+#!/bin/bash
+iptables -L FWcnt -n|gawk -v CONVFMT="%d" '{if($1 ~ "^FWcntIN"){split ($NF,N,"/");print N[1]}}'|sort -u -n -t . -k1,1 -k2,2 -k3,3 -k4,4|
+
+gawk -v CONVFMT="%d" '
+
+function print_header(Ofile){
+OUT="/var/lib/FWcnt/run_conf/"Ofile".conf"
+OUTf="/var/lib/FWcnt/run_conf/"Ofile".cfg"
+print OUT > OUTf
+print "######################################################################" >OUT
+print "# Automaticaly generated (/var/www/mrtg/gener)" >>OUT
+print "# !!!!!!! not for use with real mrtg !!!!!!" >>OUT
+print "# automaticaly generated. " >>OUT
+print "######################################################################" >>OUT
+print "Htmldir: /var/www/mrtg-rrd" >>OUT
+print "Imagedir: /var/www/mrtg-rrd" >>OUT
+print "Logdir:  /var/lib/FWcnt/FW_rrd_database" >>OUT
+print "" >>OUT
+print "WriteExpires: Yes" >>OUT
+print "LogFormat: rrdtool" >>OUT
+print "" >>OUT
+print "Title[^]: Traffic Analysis for " >>OUT
+print "" >>OUT
+}
+
+function print_target(IP,TARGET,NAME,Ofile,HREF){
+   OUT="/var/lib/FWcnt/run_conf/"Ofile".conf"
+   gsub("/","_",TARGET)
+   printf("Target[%s-b]: none\n",TARGET) >> OUT
+   printf("MaxBytes[%s-b]: %s\n",TARGET,10000*128) >> OUT
+   printf("AbsMax[%s-b]: %s\n",TARGET,3280000) >> OUT
+   if(HREF==""){
+   printf("Title[%s-b]: &nbsp;bytes %s\n",TARGET,IP) >> OUT
+   }   
+   else{
+   printf("Title[%s-b]: &nbsp;bytes %s </A><A HREF=\"%s\">\n",TARGET,IP,HREF) >> OUT
+   }
+   printf("Options[%s-b]: bits\n",TARGET)>>OUT
+   printf("PageTop[%s-b]: <H1> Bytes to/from %s (%s)\n",TARGET,IP,IP)  >> OUT                  
+   printf("  %s</H1>\n  <TABLE>\n   <TR><TD>System:</TD><TD>router</TD></TR>\n",IP) >> OUT
+   printf("   <TR><TD>Maintainer:</TD><TD>krak3n</TD></TR>\n  </TABLE>\n\n") >> OUT
+
+   printf("Target[%s-p]: none\n",TARGET) >> OUT
+   printf("MaxBytes[%s-p]: %s\n",TARGET,65000) >> OUT
+   printf("AbsMax[%s-p]: %s\n",TARGET,1280000) >> OUT
+   printf("ShortLegend[%s-p]: pps\n",TARGET) >> OUT
+   printf("Options[%s-p]: nopercent,unknaszero\n",TARGET) >> OUT
+   printf("Title[%s-p]: &nbsp;pkts %s\n",TARGET,IP) >> OUT
+   printf("YLegend[%s-p]: Pkts per Second\n",TARGET) >> OUT
+   printf("PageTop[%s-p]: <H1> Pkts to/from %s\n",TARGET,IP)  >> OUT
+   printf("   </H1>\n   <TABLE>\n    <TR><TD>System:</TD><TD>router</TD></TR>\n") >> OUT
+   printf("   <TR><TD>Maintainer:</TD><TD>krak3n</TD></TR>\n  </TABLE>\n\n") >> OUT                             
+}
+
+BEGIN{
+ OUTx="/var/lib/FWcnt/run_conf/target.parent"
+ printf("")>OUTx
+ print_header("default")
+ while(getline < "/var/lib/FWcnt/etc/config" ){
+       if($1 ~ "^mrtgNET"){    
+         split($2,N,".")
+         C=16
+         if(split($3,NM,".")==4){
+               if(NM[1]==255 && NM[2]==255 && NM[3]==255) C=256-NM[4]
+         }
+         else   C=2^(32-$3)    
+         if(C>128 || C<8)C=16
+         N[4]=and(N[4],xor(255,(C-1))) 
+         NL[N[1]"."N[2]"."N[3]"."N[4]]=C
+#        print("Net "N[1]"."N[2]"."N[3]"."N[4]" "C)
+       }
+        if($1 ~ "^cntLINK"){
+               print_target($2"",$2"",$2"","default","")
+               printf("default %s\n",$2) >>OUTx
+        }
+ }
+ close("/var/lib/FWcnt/etc/config");
+}
+{
+TP="default"
+IP=$1 "/24"
+TARGET=$1."/24"
+NAME=$1"/24"
+HREF=$1"_24"
+print_target(IP,TARGET,NAME,"default",HREF)
+printf("%s %s\n",TP,TARGET) >>OUTx
+
+split(IP,IPn,".");
+netC=IPn[1]"."IPn[2]"."IPn[3]
+
+ TP=$1"_24"
+ print_header(TP)
+ i=0
+ while(i<256){
+  j=16
+  if(netC"."i in NL) j=NL[netC"."i]
+  jx=32-int(log(j)*1.5)
+#  print "j="j" jx="jx
+  IP=netC"."i"/"jx
+  TARGET=IP
+  NAME=IP
+  HREF=netC"."i"_"jx
+  print_target(IP,TARGET,NAME,TP,HREF)
+  printf("%s %s\n",TP,TARGET) >>OUTx
+  k=0
+  TPx=netC"."i"_"jx
+  HREF=""
+  print_header(TPx)
+  while(k<j){
+       IP=netC"."k+i
+       TARGET=IP
+       NAME=IP
+       print_target(IP,TARGET,NAME,TPx,HREF)
+       printf("%s %s\n",TPx,TARGET) >>OUTx
+       k++
+  }
+  i+=j
+ }
+}'
diff --git a/get_FWcnt b/get_FWcnt
new file mode 100755 (executable)
index 0000000..2be34b9
--- /dev/null
+++ b/get_FWcnt
@@ -0,0 +1,33 @@
+#!/bin/bash
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
+iptables -L  FWcnt -n -x -v 2>/dev/null|awk '{
+ if(NR<3)next;
+ if(NF==9) {
+       printf "%s %s %s %s\n",$1,$2,$8,$9
+       C1="iptables -L "$3" -n -x -v"
+       C1|getline
+       C1|getline
+       while(C1|getline){
+               if(NF==9) {
+                 printf "%s %s %s %s\n",$1,$2,$8,$9
+                 C2="iptables -L "$3" -n -x -v"
+                 C2|getline
+                 C2|getline
+                 while(C2|getline){
+                       if(NF==9) {
+                         printf "%s %s %s %s\n",$1,$2,$8,$9
+                       }
+                       if(NF==8) {
+                         printf "%s %s %s %s\n",$1,$2,$7,$8
+                       }
+                 }
+                 close(C2)
+               }
+               if(NF==8) {
+                 printf "%s %s %s %s\n",$1,$2,$7,$8
+               }
+       }
+       close(C1)
+ }
+}'
+
diff --git a/init_FWcnt b/init_FWcnt
new file mode 100755 (executable)
index 0000000..3404e99
--- /dev/null
@@ -0,0 +1,94 @@
+#!/bin/bash
+(if  [ $# -ne 1 ]; then
+       awk '{if($1=="cntNET") print $2}' /var/lib/FWcnt/etc/config
+else
+       echo "$1"       
+fi)|while read IP;do 
+NET_A=`echo $IP|awk -F. '{printf "%d",$1}'`
+NET_B=`echo $IP|awk -F. '{printf "%d",$2}'`
+NET_C=`echo $IP|awk -F. '{printf "%d",$3}'`
+if [ ${NET_A} -gt 255 ]; then 
+ NET_A=255
+fi
+if [ ${NET_B} -gt 255 ]; then 
+ NET_B=255
+fi
+if [ ${NET_C} -gt 255 ]; then 
+ NET_C=255
+fi
+iptables -N FWcnt 2>/dev/null
+
+NET_Ah=`printf "%X" ${NET_A}`
+NET_Bh=`printf "%X" ${NET_B}`
+NET_Ch=`printf "%X" ${NET_C}`
+
+iptables -L FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -n 2>/dev/null >/dev/null
+if [ $? == 0 ]; then
+       echo "Warning, counters for net ${NET_A}.${NET_B}.${NET_C}.0/24 exists...."
+else   
+
+iptables -N FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch}
+iptables -N FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch}
+
+#create counters for nets /25
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.0/25
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.128/25
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.0/25
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.128/25
+
+#create counters for nets /26
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.0/26
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.64/26
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.128/26
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.192/26
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.0/26
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.64/26
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.128/26
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.192/26
+
+#create counters for nets /27
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.0/27
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.32/27
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.64/27
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.96/27
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.128/27
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.160/27
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.192/27
+iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch} -d ${NET_A}.${NET_B}.${NET_C}.224/27
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.0/27
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.32/27
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.64/27
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.96/27
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.128/27
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.160/27
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.192/27
+iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.224/27
+
+#create subchains for counters (/28)
+i=0
+while [ $i -lt 16 ]; do
+ ih=`printf "%X" $i`
+ j=$[$i * 16 ]
+ iptables -N FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch}${ih}
+ iptables -N FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch}${ih}
+ #create counters for /29
+ iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch}${ih}  -d ${NET_A}.${NET_B}.${NET_C}.${j}/29
+ iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch}${ih}  -d ${NET_A}.${NET_B}.${NET_C}.$[${j} + 8 ]/29
+ iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch}${ih} -s ${NET_A}.${NET_B}.${NET_C}.${j}/29
+ iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch}${ih} -s ${NET_A}.${NET_B}.${NET_C}.$[${j} + 8 ]/29
+ #create counters for chunk 16 IP
+ k=0
+ while [ $k -lt 16 ]; do
+  iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch}${ih} -d ${NET_A}.${NET_B}.${NET_C}.$[ ${k} + ${j} ] -j RETURN
+  iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch}${ih} -s ${NET_A}.${NET_B}.${NET_C}.$[ ${k} + ${j} ] -j RETURN
+ k=$[$k + 1 ]
+ done
+ iptables -A FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch}  -d ${NET_A}.${NET_B}.${NET_C}.${j}/28 -j FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch}${ih}
+ iptables -A FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.${j}/28 -j FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch}${ih}
+ i=$[$i + 1 ]
+done
+
+iptables -A FWcnt -j FWcntIN_${NET_Ah}${NET_Bh}${NET_Ch}  -d ${NET_A}.${NET_B}.${NET_C}.0/24
+iptables -A FWcnt -j FWcntOUT_${NET_Ah}${NET_Bh}${NET_Ch} -s ${NET_A}.${NET_B}.${NET_C}.0/24
+fi
+done
diff --git a/wrapper/w0.cgi b/wrapper/w0.cgi
new file mode 100755 (executable)
index 0000000..6aab91b
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+C="default.cfg"
+if [ $# -eq 1 ]; then
+       C=`echo $1|awk '{print $1".cfg"}'`
+fi
+CFG=/var/lib/FWcnt/etc/${C}
+if [ -e ${CFG} ]; then
+       export MRTGRRDCONF=${CFG}
+fi
+exec /usr/lib/cgi-bin/mrtg-rrd.cgi
+
diff --git a/wrapper/w1.cgi b/wrapper/w1.cgi
new file mode 100755 (executable)
index 0000000..59e65a4
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/bash
+IPI=${PATH_INFO}  
+Cxx=`echo "${PATH_INFO}"|awk 'BEGIN{
+while (getline <"/var/lib/FWcnt/etc/target.parent"){
+ gsub("/","_")
+ TP[$2]=$1
+ }
+close("/var/lib/FWcnt/etc/target.parent")
+FS="-"
+}
+{
+gsub("/","")
+if (length($1)>4){
+split($1,IP,".")
+split($1,N,"_")
+X=strtonum(IP[4])
+IP[4]=X
+NX=strtonum(N[2])
+if(NX!=0){
+X=sprintf ("%d.%d.%d.%d_%d",IP[1],IP[2],IP[3],IP[4],NX)
+}
+else{
+X=sprintf ("%d.%d.%d.%d",IP[1],IP[2],IP[3],IP[4])
+}
+#print(TP[X])
+if(ENVIRON["PATH_INFO"] ~ ".png$") {print(TP[X]);exit 0}
+if(ENVIRON["PATH_INFO"] ~ ".html$") {print(TP[X]);exit 0}
+print X
+exit 1
+}
+else   {
+       printf("default\n");
+       }
+}'`
+if [ $? == 1 ]; then
+       export PATH_INFO="/"
+fi
+
+CFG=/var/lib/FWcnt/etc/${Cxx}.cfg
+echo $CFG >> /var/lib/FWcnt/etc/debug
+echo "incoming PATH_INFO: "$IPI >>/var/lib/FWcnt/etc/debug
+echo "PATH_INFO: $PATH_INFO" >>/var/lib/FWcnt/etc/debug
+echo $Cxx >>/var/lib/FWcnt/etc/debug
+
+if [ -e ${CFG} ]; then
+       echo "OK" >> /var/lib/FWcnt/etc/debug
+       export MRTGRRDCONF=${CFG}
+       exec /usr/lib/cgi-bin/mrtg-rrd.cgi
+else
+       echo "Content-type: text/html"
+       echo "X-Powered-By: shell"
+       echo ""
+       echo "no CFG "$CFG
+fi
diff --git a/wrapper/w2.cgi b/wrapper/w2.cgi
new file mode 100755 (executable)
index 0000000..7021ab5
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/bash
+Cxx=`echo "${PATH_INFO}"|awk 'BEGIN{
+while (getline <"/var/lib/FWcnt/etc/target.parent"){
+ gsub("/","_")
+ TP[$2]=$1
+ }
+close("/var/lib/FWcnt/etc/target.parent")
+FS="-"
+}
+{
+gsub("/","")
+if (length($1)>4){
+split($1,IP,".")
+split($1,N,"_")
+X=strtonum(IP[4])
+IP[4]=X
+NX=strtonum(N[2])
+if(NX!=0){
+X=sprintf ("%d.%d.%d.%d_%d",IP[1],IP[2],IP[3],IP[4],NX)
+}
+else{
+X=sprintf ("%d.%d.%d.%d",IP[1],IP[2],IP[3],IP[4])
+}
+#print(TP[X])
+if(ENVIRON["PATH_INFO"] ~ ".png$") {print(TP[X]);exit 0}
+if(ENVIRON["PATH_INFO"] ~ ".html$") {print(TP[X]);exit 0}
+print X
+exit 1
+}
+else   {
+       printf("default\n");
+       }
+}'`
+if [ $? == 1 ]; then
+       export PATH_INFO="/"
+fi
+
+CFG=/var/lib/FWcnt/etc/${Cxx}.cfg
+
+if [ -e ${CFG} ]; then
+       export MRTGRRDCONF=${CFG}
+       exec /usr/lib/cgi-bin/mrtg-rrd.cgi
+else
+       echo "Content-type: text/html"
+       echo "X-Powered-By: shell"
+       echo ""
+       echo "no CFG "$CFG
+fi
diff --git a/wrapper/w3.cgi b/wrapper/w3.cgi
new file mode 100755 (executable)
index 0000000..0de1580
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/bash
+awk 'BEGIN{
+  while (getline <"/var/lib/FWcnt/run_conf/target.parent"){
+    gsub("/","_")
+    TP[$2]=$1
+  }
+  close("/var/lib/FWcnt/run_conf/target.parent")
+  FS="-"
+  INP=ENVIRON["PATH_INFO"]
+  PATH_INFO=INP
+  gsub("/","",INP)
+  if (length(INP)>4){
+    split(INP,IP,".")
+    split(INP,N,"_")
+    X=strtonum(IP[4])
+    IP[4]=X
+    NX=strtonum(N[2])
+    if(NX!=0){
+      X=sprintf ("%d.%d.%d.%d_%d",IP[1],IP[2],IP[3],IP[4],NX)
+    }
+    else{
+      X=sprintf ("%d.%d.%d.%d",IP[1],IP[2],IP[3],IP[4])
+    }
+    if(ENVIRON["PATH_INFO"] ~ ".png$") {OUTX=TP[X];exit 0}
+    if(ENVIRON["PATH_INFO"] ~ ".html$") {OUTX=TP[X];exit 0}
+    OUTX=X
+    PATH_INFO="/"
+  }
+  else OUTX="default"
+}
+{#BLANK BODY
+}
+END{
+  CFG="/var/lib/FWcnt/run_conf/"OUTX".cfg"
+  if((getline <CFG)==-1){
+       printf("Content-type: text/html\n")
+       printf("X-Powered-By: awk\n\n")
+       printf("no CFG %s\n",CFG);
+  }
+  else{
+       C="MRTGRRDCONF="CFG" PATH_INFO="PATH_INFO" /usr/lib/cgi-bin/mrtg-rrd.cgi"
+       system(C)
+       close(C)
+  }
+}' /dev/null
diff --git a/wrapper/w4.cgi b/wrapper/w4.cgi
new file mode 100755 (executable)
index 0000000..aac0e96
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+awk 'BEGIN{
+  while (getline <"/var/lib/FWcnt/run_conf/target.parent"){
+    gsub("/","_")
+    TP[$2]=$1
+  }
+  close("/var/lib/FWcnt/run_conf/target.parent")
+  FS="-"
+  INP=ENVIRON["PATH_INFO"]
+  PATH_INFO=INP
+  gsub("/","",INP)
+  if (length(INP)>2){
+    split(INP,IP,".")
+    split(INP,N,"_")
+    X=strtonum(IP[4])
+    IP[4]=X
+    NX=strtonum(N[2])
+    if(NX!=0){
+      X=sprintf ("%d.%d.%d.%d_%d",IP[1],IP[2],IP[3],IP[4],NX)
+    }
+    else{
+      X=sprintf ("%d.%d.%d.%d",IP[1],IP[2],IP[3],IP[4])
+    }
+    if(X in TP){
+           OUTX=TP[X]
+    }
+    else{
+       OUTX="default"
+    }
+    if(ENVIRON["PATH_INFO"] ~ ".png$") {exit 0}
+    if(ENVIRON["PATH_INFO"] ~ ".html$") {exit 0}
+    OUTX=X
+    PATH_INFO="/"
+  }
+  else OUTX="default"
+}
+{#BLANK BODY
+}
+END{
+  CFG="/var/lib/FWcnt/run_conf/"OUTX".cfg"
+  if((getline <CFG)==-1){
+       printf("Content-type: text/html\n")
+       printf("X-Powered-By: awk\n\n")
+       printf("no CFG %s\n",CFG);
+  }
+  else{
+       C="MRTGRRDCONF="CFG" PATH_INFO="PATH_INFO" /usr/lib/cgi-bin/mrtg-rrd.cgi"
+       system(C)
+       close(C)
+  }
+}' /dev/null