--- /dev/null
+#!/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
--- /dev/null
+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
+
--- /dev/null
+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.
+
--- /dev/null
+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 ..
+
+
+
--- /dev/null
+* get name for IP/net
+
+* iptables counter setting (start/stop) from /etc/network/intrfaces
--- /dev/null
+#!/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
+
--- /dev/null
+/* 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);
+}
--- /dev/null
+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
--- /dev/null
+/* 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);
+}
--- /dev/null
+#!/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]: bytes %s\n",TARGET,IP) >> OUT
+ }
+ else{
+ printf("Title[%s-b]: 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]: 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
+ }
+}'
--- /dev/null
+#!/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)
+ }
+}'
+
--- /dev/null
+#!/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
--- /dev/null
+#!/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
+
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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