[bwm-tools-devel] COMMIT - r88 - in trunk: . bwmd doc include lib
Brought to you by:
nkukard
From: <sv...@li...> - 2006-03-07 17:44:37
|
Author: nkukard Date: 2006-03-07 17:43:37 +0000 (Tue, 07 Mar 2006) New Revision: 88 Modified: trunk/Makefile.am trunk/TODO trunk/bwmd/Makefile.am trunk/bwmd/report.c trunk/configure.ac trunk/doc/bwmtools.texi trunk/include/flow.h trunk/include/report.h trunk/lib/Makefile.am trunk/lib/xmlConf.c Log: * Various code cleanups * Added parameters... report-format Either rrd or native, updates rrd files and creates BWM Tools native logging files automagically report-filename Specify the report filename manually flow-mode Specify the mode of flow control for the said flow, either local (INPUT & OUTPUT) or forward (FORWARD), this is needed if you're shaping traffic sourcing and destined to your local box and not forwarding traffic through a firewall/router * Install RRD Tool when installing BWM Tools Modified: trunk/Makefile.am =================================================================== --- trunk/Makefile.am 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/Makefile.am 2006-03-07 17:43:37 UTC (rev 88) @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -SUBDIRS=lib bwm_firewall bwm_graph bwmd bwm_monitor doc +SUBDIRS=@RRDTOOL_DIRS@ lib bwm_firewall bwm_graph bwmd bwm_monitor doc EXTRA_DIST=include/autoclass.h include/common.h include/flow.h include/flowControl.h include/ipq.h EXTRA_DIST+=include/libipq.h include/misc.h include/report.h include/xmlConf.h Modified: trunk/TODO =================================================================== --- trunk/TODO 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/TODO 2006-03-07 17:43:37 UTC (rev 88) @@ -13,3 +13,19 @@ * bwm_firewall to generate automatic MARK values for flows * fix findFlowByName & findGroupByName, these 2 functions are similar and i'm sure can be merged * have the location of iptables-restore automatically discovered using ./configure, with override options + + +* Create /etc/bwm_tools and /var/bwm_tools on install +* BPS/KBPS/MBPS support in firewall.xml for flows +* TBF and CBQ params + - queue-manager + - prio + * Process bands in priority, dequeue 0 first, then 1 ... to n + + - prio-weighted + * Dequeue X packets or X bytes + add a weight + +* Fix up prio classifier +* Fix default queue size + len +* xmlConf queue & flow parsing has duplicated code, alot! +* Try autoassign nfmark? Modified: trunk/bwmd/Makefile.am =================================================================== --- trunk/bwmd/Makefile.am 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/bwmd/Makefile.am 2006-03-07 17:43:37 UTC (rev 88) @@ -23,13 +23,23 @@ XML_LIBS=@XML_LIBS@ XML_CFLAGS=@XML_CFLAGS@ +RRDTOOL_INCLUDEDIR=@RRDTOOL_INCLUDEDIR@ +RRDTOOL_LIBS=@RRDTOOL_LIBS@ +RRDTOOL_LDADDS=@RRDTOOL_LDADDS@ +RRDTOOL_VER=@RRDTOOL_VER@ + CONFIG_DIR=/etc/bwm_tools CONFIG_FILE=$(CONFIG_DIR)/firewall.xml -LOG_DIR=/var/bwm_tools bin_PROGRAMS = bwmd -bwmd_SOURCES = report.c flowControl.c logging.c ipq.c flow.c libipq.c autoclass.c bwmd.c -bwmd_LDADD = $(top_builddir)/lib/libbwm.la -bwmd_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(XML_CFLAGS) -DCONFIG_FILE=\"$(CONFIG_FILE)\" -DLOG_DIR=\"$(LOG_DIR)\" $(AM_CFLAGS) -bwmd_LDFLAGS = $(GLIB_LIBS) $(XML_LIBS) +bwmd_SOURCES = report.c flowControl.c logging.c ipq.c libipq.c flow.c autoclass.c bwmd.c +bwmd_DEPENDENCIES = $(RRDTOOL_LDADDS) +bwmd_LDADD = $(top_builddir)/lib/libbwm.la $(RRDTOOL_LDADDS) +bwmd_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(XML_CFLAGS) $(RRDTOOL_INCLUDEDIR) -DCONFIG_FILE=\"$(CONFIG_FILE)\" \ + -DRRDTOOL_VER=$(RRDTOOL_VER) $(AM_CFLAGS) +bwmd_LDFLAGS = $(GLIB_LIBS) $(XML_LIBS) $(RRDTOOL_LIBS) +# Build rrdtool if we need it +$(top_builddir)/rrdtool/src/librrd.la: + $(MAKE) $(AM_MAKEFLAGS) -C ../rrdtool + Modified: trunk/bwmd/report.c =================================================================== --- trunk/bwmd/report.c 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/bwmd/report.c 2006-03-07 17:43:37 UTC (rev 88) @@ -31,12 +31,13 @@ #include <time.h> #include <unistd.h> #include "flow.h" +#include "misc.h" #include "report.h" // Function to write a log entry to the report file -static void *writeEntry(void *data) +static void *writeNativeEntry(void *data) { struct reportData_t *reportData = (struct reportData_t*) data; struct stat statBuf; @@ -45,28 +46,23 @@ int opRes; int err = 0; int fd; - char filename[MAX_NAMELEN]; - // Blank file header & filename + // Blank file header memset(&fileHeader,'\0',sizeof(struct aLogFileHeader_t)); - memset(&filename,'\0',MAX_NAMELEN); - // Lets get our filename... - snprintf(filename,MAX_NAMELEN,"%s/%s.dat",LOG_DIR,reportData->ref); - // Get stats for file - result = stat(filename,&statBuf); + result = stat(reportData->reportFilename,&statBuf); if (result == 0) { // Stats was ok, open it - fd = open(filename,O_RDWR); + fd = open(reportData->reportFilename,O_RDWR); if (fd > 0) { opRes = read(fd,&fileHeader,sizeof(struct aLogFileHeader_t)); if (opRes != sizeof(struct aLogFileHeader_t)) { - logMessage(LOG_DEBUG, "Error reading header from \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Error reading header from \"%s\": %s\n",reportData->reportFilename,strerror(errno)); err = 1; } // If no errors seek... @@ -76,7 +72,7 @@ opRes = lseek(fd,0,SEEK_END); if (opRes < 0) { - logMessage(LOG_DEBUG, "Error seeking end of file \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Error seeking end of file \"%s\": %s\n",reportData->reportFilename,strerror(errno)); err = 1; } } @@ -87,7 +83,7 @@ opRes = write(fd,&reportData->entry,sizeof(struct aLogFileEntry_t)); if (opRes != sizeof(struct aLogFileEntry_t)) { - logMessage(LOG_DEBUG, "Error writing record to file \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Error writing record to file \"%s\": %s\n",reportData->reportFilename,strerror(errno)); err = 1; } else @@ -107,7 +103,7 @@ opRes = lseek(fd,0,SEEK_SET); if (opRes < 0) { - logMessage(LOG_DEBUG, "Error seeking beginning of file \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Error seeking beginning of file \"%s\": %s\n",reportData->reportFilename,strerror(errno)); err = 1; } } @@ -118,28 +114,28 @@ opRes = write(fd,&fileHeader,sizeof(struct aLogFileHeader_t)); if (opRes != sizeof(struct aLogFileHeader_t)) { - logMessage(LOG_DEBUG, "Error writing header to file \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Error writing header to file \"%s\": %s\n",reportData->reportFilename,strerror(errno)); err = 1; } } close(fd); } else - fprintf(stderr,"Stat error on \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR,"Failed to open file \"%s\": %s\n",reportData->reportFilename,strerror(errno)); } else { // Check if file doesn't exist if (errno == ENOENT) { - logMessage(LOG_DEBUG, "Creating report file %s\n",filename); + logMessage(LOG_ERR, "Creating report file %s\n",reportData->reportFilename); // If not create it - fd = open(filename,O_CREAT|O_RDWR,S_IREAD|S_IWRITE); + fd = open(reportData->reportFilename,O_CREAT|O_RDWR,S_IREAD|S_IWRITE); if (fd > 0) { // Build header memcpy(&fileHeader.fileVer,FILE_VER_CURRENT,strlen(FILE_VER_CURRENT)); - memcpy(&fileHeader.ref,&reportData->ref,strlen(reportData->ref)); + memcpy(&fileHeader.ref,reportData->ref,strlen(reportData->ref)); fileHeader.start = reportData->entry.unixStampStart; fileHeader.end = reportData->entry.unixStampStart; fileHeader.recs = 1; @@ -148,7 +144,7 @@ opRes = write(fd,&fileHeader,sizeof(struct aLogFileHeader_t)); if (opRes != sizeof(struct aLogFileHeader_t)) { - logMessage(LOG_DEBUG, "Error writing header to \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Error writing header to \"%s\": %s\n",reportData->reportFilename,strerror(errno)); err = 1; } // If no errors write more... @@ -157,17 +153,17 @@ opRes = write(fd,&reportData->entry,sizeof(struct aLogFileEntry_t)); if (opRes != sizeof(struct aLogFileEntry_t)) { - logMessage(LOG_DEBUG, "Error writing record to \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Error writing record to \"%s\": %s\n",reportData->reportFilename,strerror(errno)); err = 1; } } close(fd); } else - logMessage(LOG_DEBUG, "Stat error on \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Failed to create \"%s\": %s\n",reportData->reportFilename,strerror(errno)); } else - logMessage(LOG_DEBUG, "Failed to open file \"%s\": %s\n",filename,strerror(errno)); + logMessage(LOG_ERR, "Failed to open file \"%s\": %s\n",reportData->reportFilename,strerror(errno)); } return(NULL); @@ -175,6 +171,62 @@ +// Function to write a log entry to an RRD file +static void *writeRRDEntry(void *data) +{ + struct reportData_t *reportData = (struct reportData_t*) data; + struct stat statBuf; + int result; + int opRes; + int err = 0; + int fd; + + + // Get stats for file + result = stat(reportData->reportFilename,&statBuf); + if (result == 0) + { + char **params; + int numParams = 0; + int i; + + + // Create just a little mem for us to begin with + params = (char **) malloc0(sizeof(char*)); + + // Add update string + ADD_SINGLE_PARAM(params,numParams, + "%i@%i:%i:%i:%i", + reportData->entry.unixStampEnd, + reportData->entry.bytesSeen, + reportData->entry.packetsSeen, + reportData->entry.packetsBursted, + reportData->entry.packetsDropped + ); + + // Try the update + if ((i = rrd_update_r(reportData->reportFilename,"bytes:packets:bursted:dropped",numParams,params)) < 0) + logMessage(LOG_ERR,"Failed to update RRD file %s: %s\n",reportData->reportFilename,rrd_get_error()); + + // Free memory + for (i = 0; i < numParams; i++) + free(params[i]); + free(params); + } + else + { + // Check if file doesn't exist + if (errno == ENOENT) + logMessage(LOG_ERR, "Please create \"%s\" first\n",reportData->reportFilename); + else + logMessage(LOG_ERR, "Failed to open file \"%s\": %s\n",reportData->reportFilename,strerror(errno)); + } + + return(NULL); +} + + + // Main reporting module void *reportRunner(void *data) { @@ -208,9 +260,9 @@ // Check if we gonna pump to disk if (flow->counterRemaining < 1) { - // Build our structure to pump into the file - strncpy(reportData.ref,flow->flowName,MAX_REFLEN); + reportData.ref = flow->flowName; + reportData.reportFilename = flow->reportFilename; reportData.entry.unixStampStart = flow->lastDumpTimestamp; flow->lastDumpTimestamp = time(NULL); reportData.entry.unixStampEnd = flow->lastDumpTimestamp; @@ -220,8 +272,16 @@ reportData.entry.packetsSeen = flow->counter.pktCount; reportData.entry.packetsBursted = flow->counter.pktBursted; reportData.entry.packetsDropped = flow->counter.pktDropped; - // Log to file - writeEntry(&reportData); + + // Check what format we're working with + if (flow->reportFormat == REPORT_FORMAT_NATIVE) + // Log to file + writeNativeEntry(&reportData); + else if (flow->reportFormat == REPORT_FORMAT_RRD) + writeRRDEntry(&reportData); + else + logMessage(LOG_ERR, "ERROR: Internal error, report format not understood for \"%s\"\n",flow->flowName); + // Reset counters flow->counterRemaining = flow->counterTimeout; reset = 1; @@ -267,8 +327,7 @@ // Check if we gonna pump to disk if (group->counterRemaining < 1) { - - // Build our structure to pump into the file + // Build our structure and write below strncpy(reportData.ref,group->groupName,MAX_REFLEN); reportData.entry.unixStampStart = group->lastDumpTimestamp; group->lastDumpTimestamp = time(NULL); @@ -279,8 +338,16 @@ reportData.entry.packetsSeen = group->counter.pktCount; reportData.entry.packetsBursted = group->counter.pktBursted; reportData.entry.packetsDropped = group->counter.pktDropped; - // Log to file - writeEntry(&reportData); + + // Check what format we're working with + if (group->reportFormat == REPORT_FORMAT_NATIVE) + // Log to file + writeNativeEntry(&reportData); + else if (group->reportFormat == REPORT_FORMAT_RRD) + writeRRDEntry(&reportData); + else + logMessage(LOG_ERR, "ERROR: Internal error, report format not understood for \"%s\"\n",group->groupName); + // Reset counters group->counterRemaining = group->counterTimeout; reset = 1; Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/configure.ac 2006-03-07 17:43:37 UTC (rev 88) @@ -20,7 +20,7 @@ */ AC_PREREQ(2.57) -AC_INIT([bwm_tools],[200602012132]) +AC_INIT([bwm_tools],[devel]) AC_CONFIG_SRCDIR([bwm_monitor/bwm_monitor.c]) AC_CONFIG_HEADER([config.h]) @@ -58,6 +58,7 @@ [ --with-rrdtool-source Specify that you have the rrdtool sources in the main build dir], [ AC_CONFIG_SUBDIRS(rrdtool) + RRDTOOL_DIRS="rrdtool" RRDTOOL_LDADDS="\$(top_builddir)/rrdtool/src/librrd.la" RRDTOOL_INCLUDEDIR="-I\$(top_builddir)/rrdtool/src" ], @@ -87,7 +88,7 @@ RRDTOOL_LIBS="-lm -lrrd" ]) -AC_SUBST(RRDTOOL_LDADDS RRDTOOL_LIBS RRDTOOL_INCLUDEDIR RRDTOOL_VER) +AC_SUBST(RRDTOOL_DIRS RRDTOOL_LDADDS RRDTOOL_LIBS RRDTOOL_INCLUDEDIR RRDTOOL_VER) # Checks for header files. AC_HEADER_STDC Modified: trunk/doc/bwmtools.texi =================================================================== --- trunk/doc/bwmtools.texi 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/doc/bwmtools.texi 2006-03-07 17:43:37 UTC (rev 88) @@ -824,6 +824,20 @@ seconds. Minimum value for this parameter is 30. @* @item +@cindex report-format +@code{report-format="@dfn{native}|@dfn{rrd}"} - Optional parameter to specify +the format of the report file. Defaults to @dfn{native}. Note: if using +@dfn{rrd}, you MUST create the RRDTool file before running bwmd. It is not +created automagically. For the @dfn{native} format @code{report-filename} +would default to @code{/var/bwm_tools/flow_name.dat}, for the @dfn{rrd} format +@code{report-filename} would default to @code{/var/bwm_tools/flow_name.rrd}. +@* +@item +@cindex report-filename +@code{report-filename="@dots{}"} - Optional parameter to specify +the report filename. +@* +@item @cindex prio-classifier @code{prio-classifier="@dots{}"} - Optional parameter to specify an automatic traffic prioritization classifier. This parameter defaults to the @dfn{none} Modified: trunk/include/flow.h =================================================================== --- trunk/include/flow.h 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/include/flow.h 2006-03-07 17:43:37 UTC (rev 88) @@ -128,10 +128,13 @@ unsigned int accumMs; // Accumulated number of microseconds struct timeval lastCreditCalc; // Last "timeval" that we calculated additional credit struct pktStat_t running; // This is the running counter used for stats & logging - + + // Reporting stuff int lastDumpTimestamp; int counterTimeout; // STATIC - length between file logs int counterRemaining; + int reportFormat; + char *reportFilename; }; @@ -157,6 +160,8 @@ int lastDumpTimestamp; int counterTimeout; // STATIC - length between file logs int counterRemaining; + int reportFormat; + char *reportFilename; // Flows we "contain" GList *flowList; Modified: trunk/include/report.h =================================================================== --- trunk/include/report.h 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/include/report.h 2006-03-07 17:43:37 UTC (rev 88) @@ -37,7 +37,11 @@ #define FILE_VER_CURRENT FILE_VER_0_2 #define FILE_VER_0_2 "BWM_VER-0.2" +// Report formats we can generate +#define REPORT_FORMAT_NATIVE 0 +#define REPORT_FORMAT_RRD 1 + // File format stuff... struct aLogFileHeader_t { @@ -64,9 +68,10 @@ // Function passed structure for logging struct reportData_t { - char ref[MAX_REFLEN]; + char *ref; int counterTimeout; struct aLogFileEntry_t entry; + char *reportFilename; }; Modified: trunk/lib/Makefile.am =================================================================== --- trunk/lib/Makefile.am 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/lib/Makefile.am 2006-03-07 17:43:37 UTC (rev 88) @@ -23,9 +23,10 @@ XML_LIBS=@XML_LIBS@ XML_CFLAGS=@XML_CFLAGS@ +LOG_DIR=/var/bwm_tools lib_LTLIBRARIES = libbwm.la libbwm_la_SOURCES = xmlConf.c misc.c -libbwm_la_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(XML_CFLAGS) $(AM_CFLAGS) +libbwm_la_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(XML_CFLAGS) -DLOG_DIR=\"$(LOG_DIR)\" $(AM_CFLAGS) libbwm_la_LDFLAGS = $(GLIB_LIBS) $(XML_LIBS) -version-info 1:0:0 Modified: trunk/lib/xmlConf.c =================================================================== --- trunk/lib/xmlConf.c 2006-03-06 09:56:29 UTC (rev 87) +++ trunk/lib/xmlConf.c 2006-03-07 17:43:37 UTC (rev 88) @@ -32,6 +32,7 @@ #include "autoclass.h" #include "common.h" #include "flow.h" +#include "report.h" #include "xmlConf.h" @@ -357,13 +358,13 @@ if (!strcmp(key,"to-src") && !done) { // Make sure to-src is only used in SNAT section - if ((strcmp(target, "SNAT") == 0)) + if (!strcmp(target, "SNAT")) { snprintf(tmp,BUFFER_SIZE,"--to-source %s ",value); strncat(buffer,tmp,BUFFER_SIZE); } else - fprintf(stderr,"ERROR: Tag parameter \"to-src\" is only valid in the <snat> tag, ignoring\n"); + fprintf(stderr,"ERROR: Tag parameter \"to-src\" is only valid in the <snat> tag. Ignoring!\n"); done = 1; } @@ -371,13 +372,13 @@ if (!strcmp(key,"to-dst") && !done) { // Make sure to-dst is only used in DNAT section - if ((strcmp(target, "DNAT") == 0)) + if (!strcmp(target, "DNAT")) { snprintf(tmp,BUFFER_SIZE,"--to-destination %s ",value); strncat(buffer,tmp,BUFFER_SIZE); } else - fprintf(stderr,"ERROR: Tag parameter \"to-dst\" is only valid in the <dnat> tag, ignoring\n"); + fprintf(stderr,"ERROR: Tag parameter \"to-dst\" is only valid in the <dnat> tag. Ignoring!\n"); done = 1; } @@ -385,13 +386,13 @@ if (!strcmp(key,"to-ports") && !done) { // Make sure to-ports is only used in DNAT section - if ((strcmp(target, "MASQUERADE") == 0)) + if (!strcmp(target, "MASQUERADE")) { snprintf(tmp,BUFFER_SIZE,"--to-ports %s ",value); strncat(buffer,tmp,BUFFER_SIZE); } else - fprintf(stderr,"ERROR: Tag parameter \"to-ports\" is only valid in the <masq> tag, ignoring\n"); + fprintf(stderr,"ERROR: Tag parameter \"to-ports\" is only valid in the <masq> tag. Ignoring!\n"); done = 1; } @@ -402,7 +403,7 @@ // Check if we must complain if (!done) { - fprintf(stderr,"ERROR: Option \"%s\" no recognized\n",key); + fprintf(stderr,"ERROR: Option \"%s\" not recognized. Ignoring!\n",key); } } @@ -449,6 +450,10 @@ done = 1; if (!done && !strcmp(key,"report-timeout")) done = 1; + if (!done && !strcmp(key,"report-format")) + done = 1; + if (!done && !strcmp(key,"report-filename")) + done = 1; if (!done && !strcmp(key,"prio-classifier")) done = 1; if (!done && !strcmp(key,"burst-rate")) @@ -467,11 +472,13 @@ done = 1; if (!done && !strcmp(key,"burst-threshold")) done = 1; + if (!done && !strcmp(key,"flow-mode")) + done = 1; // Check if we must complain if (!done) { - fprintf(stderr,"ERROR: Flow option \"%s\" not recognized\n",key); + fprintf(stderr,"ERROR: Flow option \"%s\" not recognized. Ignoring!\n",key); } } @@ -629,14 +636,14 @@ // First check if our name is valid if (!moduleName) { - fprintf(stderr,"ERROR: Tag <LOAD /> requires a name\n"); + fprintf(stderr,"ERROR: Tag <LOAD /> requires a name. Ignoring!\n"); ok = 0; } // Then if we a duplicate if (ok && g_hash_table_lookup(moduleHash,moduleName)) { - fprintf(stderr,"ERROR: Duplicate module %s in MODULES section\n",moduleName); + fprintf(stderr,"ERROR: Duplicate module %s in MODULES section. Ignoring!\n",moduleName); ok = 0; } @@ -652,7 +659,7 @@ } } else - fprintf(stderr,"WARNING: Unknown tag %s in MODULES section\n",moduleNode->name); + fprintf(stderr,"WARNING: Unknown tag %s in MODULES section. Ignoring!\n",moduleNode->name); moduleNode = moduleNode->next; } @@ -666,7 +673,7 @@ // Check if we knew what the tag was if (!validTag) - fprintf(stderr,"WARNING: Unknown tag %s in GLOBAL section\n",myNode->name); + fprintf(stderr,"WARNING: Unknown tag %s in GLOBAL section. Ignoring!\n",myNode->name); // Advance "class" myNode = myNode->next; @@ -698,7 +705,9 @@ unsigned long int nfmark, unsigned char prioClassifier, float parent_th, - int reportTimeout) + int reportFormat, + int reportTimeout, + char *reportFilename) { int i; struct flow_t *flow = (struct flow_t*) malloc(sizeof(struct flow_t)); @@ -787,7 +796,34 @@ flow->running.pktSize = 0; flow->running.pktDropped = 0; flow->running.pktBursted = 0; + + // Reporting stuff + flow->reportFormat = reportFormat; + if (!reportFilename) + { + char filename[MAX_NAMELEN]; + + // Blank filename + memset(&filename,'\0',MAX_NAMELEN); + + // Generate our filename + switch (flow->reportFormat) + { + case REPORT_FORMAT_NATIVE: + snprintf(filename,MAX_NAMELEN,"%s/%s.dat",LOG_DIR,flow->flowName); + break; + + case REPORT_FORMAT_RRD: + snprintf(filename,MAX_NAMELEN,"%s/%s.rrd",LOG_DIR,flow->flowName); + break; + } + + flow->reportFilename = strdup(filename); + } + else + flow->reportFilename = strdup(reportFilename); + // Verify everything is ok... if (flow->statsLen == 0) flow->statsLen = 10; @@ -805,6 +841,7 @@ if (flow->maxQueueLen == -1) { if (flow->maxRate != 0) + // max rate / 2 (half a second) / 750 (half of MTU) flow->maxQueueLen = ((flow->burstRate + flow->maxRate) / 2 / 750) * 2; // Seems an OK value for normal use? else flow->maxQueueLen = 0; @@ -858,7 +895,9 @@ static struct group_t *createGroup( char *groupName, long int statsLen, + int reportFormat, int reportTimeout, + char *reportFilename, GList *flowList) { struct group_t *group = (struct group_t *) malloc(sizeof(struct group_t)); @@ -891,7 +930,32 @@ // Report stuff group->counterTimeout = reportTimeout; group->counterRemaining = reportTimeout; + group->reportFormat = reportFormat; + if (!reportFilename) + { + char filename[MAX_NAMELEN]; + + // Blank filename + memset(&filename,'\0',MAX_NAMELEN); + + // Generate our filename + switch (group->reportFormat) + { + case REPORT_FORMAT_NATIVE: + snprintf(filename,MAX_NAMELEN,"%s/%s.dat",LOG_DIR,group->groupName); + break; + + case REPORT_FORMAT_RRD: + snprintf(filename,MAX_NAMELEN,"%s/%s.rrd",LOG_DIR,group->groupName); + break; + } + + group->reportFilename = strdup(filename); + } + else + group->reportFilename = strdup(reportFilename); + // Our list of flows group->flowList = flowList; @@ -940,7 +1004,7 @@ struct flowData_t createFlowData(char *filename) { xmlDocPtr doc; - xmlNodePtr cur; + xmlNodePtr cur; GList *pktQueues = NULL; GList *flows = NULL, *groups = NULL, *groupItem; struct flowData_t ret; @@ -961,8 +1025,6 @@ GHashTable *tagProperties = getProperties(node); -// fprintf(stderr,"Tag: %s\n",node->name); - // We are a flow... if (!xmlStrcmp(node->name, (const xmlChar *) "flow")) { @@ -980,15 +1042,13 @@ if (ok) { - char *p; + char *p, *reportFilename; long int statsLen, maxQueueSize, maxQueueLen, maxRate, burstRate, reportTimeout; unsigned long int nfmark; - unsigned char prioClassifier; + unsigned char prioClassifier, reportFormat; float parent_th; -// fprintf(stderr," Flow found: %s\n",flowName); - // Grab all properties we need p = g_hash_table_lookup(tagProperties,"stats-len"); statsLen = p ? atol(p) : 10; @@ -1006,7 +1066,7 @@ burstRate = p ? atol(p) : -1; if (burstRate < maxRate && burstRate > 0) { - fprintf(stderr,"ERROR: %s - Tag \"burst-rate\" cannot be less than max-rate\n",flowName); + fprintf(stderr,"ERROR: %s - Tag \"burst-rate\" cannot be less than max-rate. Setting to -1.\n",flowName); burstRate = -1; } @@ -1016,14 +1076,28 @@ p = g_hash_table_lookup(tagProperties,"burst-threshold"); parent_th = p ? atof(p) : -1; + if ((p = g_hash_table_lookup(tagProperties,"report-format")) != NULL) + { + if (strcasecmp(p,"native") == 0) + reportFormat = REPORT_FORMAT_NATIVE; + else if (strcasecmp(p,"rrd") == 0) + reportFormat = REPORT_FORMAT_RRD; + else + fprintf(stderr,"ERROR: %s - Tag value for \"report-format\" is invalid, please read manual. Ignoring!\n",flowName); + } + else + reportFormat = REPORT_FORMAT_NATIVE; + p = g_hash_table_lookup(tagProperties,"report-timeout"); reportTimeout = p ? atol(p) : 0; if (reportTimeout < 30 && reportTimeout > 0) { - fprintf(stderr,"ERROR: %s - Tag \"report-timeout\" cannot be below 30 (seconds)\n",flowName); + fprintf(stderr,"ERROR: %s - Tag \"report-timeout\" cannot be below 30 (seconds). Setting to 30 seconds.\n",flowName); reportTimeout = 30; } - + + reportFilename = g_hash_table_lookup(tagProperties,"report-filename"); + // Work out automatic classifier to use if ((p = g_hash_table_lookup(tagProperties,"prio-classifier")) != NULL) { @@ -1034,14 +1108,14 @@ else if (strcasecmp(p,"none") == 0) prioClassifier = AUTOCLASS_NONE; else - fprintf(stderr,"ERROR: %s - Tag value for \"prio-classifier\" is invalid, please read manual\n",flowName); + fprintf(stderr,"ERROR: %s - Tag value for \"prio-classifier\" is invalid, please read manual. Ignoring!\n",flowName); } else prioClassifier = AUTOCLASS_NONE; // Create our flow newFlow = createFlow(flowName,parentFlow,statsLen,maxQueueSize,maxQueueLen,maxRate,burstRate,nfmark, - prioClassifier,parent_th,reportTimeout); + prioClassifier,parent_th,reportFormat,reportTimeout,reportFilename); flows = g_list_append(flows,newFlow); } @@ -1064,8 +1138,9 @@ if (ok) { - char *p; + char *p, *reportFilename; long int statsLen, reportTimeout; + unsigned char prioClassifier, reportFormat; GList *flowList; struct group_t *newGroup; @@ -1074,17 +1149,31 @@ p = g_hash_table_lookup(tagProperties,"stats-len"); statsLen = p ? atol(p) : 10; + if ((p = g_hash_table_lookup(tagProperties,"report-format")) != NULL) + { + if (strcasecmp(p,"native") == 0) + reportFormat = REPORT_FORMAT_NATIVE; + else if (strcasecmp(p,"rrd") == 0) + reportFormat = REPORT_FORMAT_RRD; + else + fprintf(stderr,"ERROR: %s - Tag value for \"report-format\" is invalid, please read manual. Ignoring!\n",groupName); + } + else + reportFormat = REPORT_FORMAT_NATIVE; + p = g_hash_table_lookup(tagProperties,"report-timeout"); reportTimeout = p ? atol(p) : 0; if (reportTimeout < 30 && reportTimeout > 0) { - fprintf(stderr,"ERROR: Tag \"report-timeout\" cannot be below 30 (seconds)\n"); + fprintf(stderr,"ERROR: %s - Tag \"report-timeout\" cannot be below 30 (seconds)\n",groupName); reportTimeout = 30; } + reportFilename = g_hash_table_lookup(tagProperties,"report-filename"); + flowList = splitContents(node); // Create our group - newGroup = createGroup(groupName,statsLen,reportTimeout,flowList); + newGroup = createGroup(groupName,statsLen,reportFormat,reportTimeout,reportFilename,flowList); groups = g_list_append(groups,newGroup); } validTag = 1; @@ -1181,9 +1270,9 @@ } // Check if we have the right root element & block - if (xmlStrcmp(cur->name, (const xmlChar *) "firewall")) + if (xmlStrcmp(cur->name, (const xmlChar *) "firewall")) { - fprintf(stderr,"ERROR: Document of the wrong type, root node != firewall\n"); + fprintf(stderr,"ERROR: Document of the wrong type, root node is not \"firewall\"\n"); xmlFreeDoc(doc); return(ret); } @@ -1217,7 +1306,7 @@ struct flow_t *tmpFlow = flowItem->data; // Compare flow name to the content list inside the group - if (strcmp((char *) contentItem->data, tmpFlow->flowName) == 0) + if (!strcmp((char *) contentItem->data, tmpFlow->flowName)) { // If it matches, check we arn't listed twice if (!g_list_find(tmpFlow->groups,tmpGroup)) @@ -1375,9 +1464,10 @@ { GHashTable *tmpProp; char *nfmark; + char *flowMode; struct confACLChain_t *tmpChain; + char *ruleName; char *chainName; - char *ruleName; GList *contentList; struct confACLRule_t *tmpRule; char *cmd_line; @@ -1389,26 +1479,42 @@ // Loop while (node) { + int trafficMatchChain = 0; int validTag = 0; // Grab our properties tmpProp = getProperties(node); nfmark = g_hash_table_lookup(tmpProp,"nfmark"); - + flowMode = g_hash_table_lookup(tmpProp,"flow-mode"); + + // Check for a flow queue if (!xmlStrcmp(node->name, (const xmlChar *) "queue")) { // Process ourselves if (nfmark) { - chainName = "FORWARD"; - - // Grab chain... - tmpChain = lookupChain(chainHash,chainName); - ruleList = tmpChain->ruleList; - ruleName = g_hash_table_lookup(tmpProp,"name"); + + // trafficMatchChain = 1 means we match for FORWARD traffic + // trafficMatchChain = 2 means we match for INPUT & OUTPUT traffic + if (!flowMode) + trafficMatchChain = 1; + else + { + if (!strcmp(flowMode, "local")) + trafficMatchChain = 2; + else if (!strcmp(flowMode, "forward")) + trafficMatchChain = 1; + } + // Check if we managed to decipher the flow-mode parameter + if (trafficMatchChain == 0) + { + fprintf(stderr,"ERROR: flow-mode is invalid!\n"); + goto next; + } + contentList = splitContents(node); tmpRule = (struct confACLRule_t*) malloc(sizeof(struct confACLRule_t)); @@ -1425,12 +1531,47 @@ else { // Build our ruleSet - cmd_line = createTrafficRuleset(tmpProp); - tmpChain->ruleset = g_list_concat(tmpChain->ruleset, - createRuleset(classHash,tmpRule->classList, - chainName,tmpRule->target,NULL,cmd_line)); + cmd_line = createTrafficRuleset(tmpProp); + + switch (trafficMatchChain) + { + case 1: + // Grab chain... + tmpChain = lookupChain(chainHash,"FORWARD"); + ruleList = tmpChain->ruleList; + // Create rule + tmpChain->ruleset = g_list_concat(tmpChain->ruleset, + createRuleset(classHash,tmpRule->classList, + "FORWARD",tmpRule->target,NULL,cmd_line)); + // Append rule + ruleList = g_list_append(ruleList,tmpRule); + break; + + + case 2: + // Grab chain... + tmpChain = lookupChain(chainHash,"INPUT"); + ruleList = tmpChain->ruleList; + // Create rule + tmpChain->ruleset = g_list_concat(tmpChain->ruleset, + createRuleset(classHash,tmpRule->classList, + "INPUT",tmpRule->target,NULL,cmd_line)); + // Append rule + ruleList = g_list_append(ruleList,tmpRule); + + // Grab chain... + tmpChain = lookupChain(chainHash,"OUTPUT"); + ruleList = tmpChain->ruleList; + // Create rule + tmpChain->ruleset = g_list_concat(tmpChain->ruleset, + createRuleset(classHash,tmpRule->classList, + "OUTPUT",tmpRule->target,NULL,cmd_line)); + // Append rule + ruleList = g_list_append(ruleList,tmpRule); + break; + + } - ruleList = g_list_append(ruleList,tmpRule); } } validTag = 1; @@ -1441,13 +1582,26 @@ // Process ourselves if (nfmark) { - chainName = "FORWARD"; - - // Grab chain... - tmpChain = lookupChain(chainHash,chainName); - ruleList = tmpChain->ruleList; - ruleName = g_hash_table_lookup(tmpProp,"name"); + + // trafficMatchChain = 1 means we match for FORWARD traffic + // trafficMatchChain = 2 means we match for INPUT & OUTPUT traffic + if (!flowMode) + trafficMatchChain = 1; + else + { + if (!strcmp(flowMode, "local")) + trafficMatchChain = 2; + else if (!strcmp(flowMode, "forward")) + trafficMatchChain = 1; + } + // Check if we managed to decipher the flow-mode parameter + if (trafficMatchChain == 0) + { + fprintf(stderr,"ERROR: flow-mode is invalid!\n"); + goto next; + } + contentList = splitContents(node); tmpRule = (struct confACLRule_t*) malloc(sizeof(struct confACLRule_t)); @@ -1464,12 +1618,43 @@ else { // Build our ruleSet - cmd_line = createTrafficRuleset(tmpProp); - tmpChain->ruleset = g_list_concat(tmpChain->ruleset, - createRuleset(classHash,tmpRule->classList, - chainName,tmpRule->target,NULL,cmd_line)); - - ruleList = g_list_append(ruleList,tmpRule); + cmd_line = createTrafficRuleset(tmpProp); + + switch (trafficMatchChain) + { + case 1: + // Grab chain... + tmpChain = lookupChain(chainHash,"FORWARD"); + ruleList = tmpChain->ruleList; + // Create rule + tmpChain->ruleset = g_list_concat(tmpChain->ruleset, + createRuleset(classHash,tmpRule->classList, + "FORWARD",tmpRule->target,NULL,cmd_line)); + // Append + ruleList = g_list_append(ruleList,tmpRule); + break; + case 2: + // Grab chain... + tmpChain = lookupChain(chainHash,"INPUT"); + ruleList = tmpChain->ruleList; + // Create rule + tmpChain->ruleset = g_list_concat(tmpChain->ruleset, + createRuleset(classHash,tmpRule->classList, + "INPUT",tmpRule->target,NULL,cmd_line)); + // Append + ruleList = g_list_append(ruleList,tmpRule); + + // Grab chain... + tmpChain = lookupChain(chainHash,"OUTPUT"); + ruleList = tmpChain->ruleList; + // Create rule + tmpChain->ruleset = g_list_concat(tmpChain->ruleset, + createRuleset(classHash,tmpRule->classList, + "OUTPUT",tmpRule->target,NULL,cmd_line)); + // Append + ruleList = g_list_append(ruleList,tmpRule); + break; + } } } // Parse child flow... see if its embedded @@ -1487,7 +1672,8 @@ // Check if the tag we had was valid if (!validTag) fprintf(stderr,"WARNING: Unknown tag %s\n",node->name); - + +next: node = node->next; } } |