"Fossies" - the Fresh Open Source Software archive 
Member "bwm_tools-0.3.0/bwm_firewall/bwm_firewall.c" of archive bwm_tools-0.3.0.tar.gz:
/*
* bwm_firewall.c - BWM Firewall
* Copyright (C) 2003-2006, Linux Based Systems Design
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 25/05/2003 - Nigel Kukard <nkukard@lbsd.net>
* * Initial design
*/
#include <getopt.h>
#include <glib.h>
#include <errno.h>
#include <fcntl.h>
#include <libxml/parser.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "../config.h"
#include "common.h"
#include "xmlConf.h"
// return current date string like
// Sun Jan 2 21:52:25 2005
static char *date2str(char *buffer)
{
time_t t = time(NULL);
sprintf(buffer, "%s", ctime(&t));
return buffer;
}
// Function to build a list of rules which iptables-restore takes
static GList *createFirewallRules(char *filename, char resetCounters)
{
xmlDocPtr doc;
xmlNodePtr cur;
GHashTable *classHash = NULL;
GHashTable *fwHash = NULL;
GList *result = NULL;
struct confACLTable_t *tmpTable;
struct confACLChain_t *aChain;
char *tableList[] = {"filter","mangle",NULL};
char *tableName;
int i;
char counters[7] = "";
struct stat fstat;
// Loop with a table
void processTable(gpointer p_key, gpointer p_value, gpointer p_user_data)
{
char *aRule;
char *tableName = (char *) p_key;
struct confACLTable_t *table = (struct confACLTable_t*) p_value;
// Create chains...
void processChains(gpointer p1_key, gpointer p1_value, gpointer p1_user_data)
{
struct confACLChain_t *chain = (struct confACLChain_t*) p1_value;
aRule = (char *) malloc0(BUFFER_SIZE);
// Check if we have a default target for the chain or not
if (chain->defaultTarget)
snprintf(aRule,BUFFER_SIZE,":%s %s%s\n",chain->name,chain->defaultTarget,counters);
else
snprintf(aRule,BUFFER_SIZE,":%s -%s\n",chain->name,counters);
result = g_list_append(result,aRule);
}
// Print out rules
void processRules(gpointer p1_key, gpointer p1_value, gpointer p1_user_data)
{
struct confACLChain_t *chain = (struct confACLChain_t*) p1_value;
// And each item therein
void processRuleset(gpointer data, gpointer user_data)
{
char *rule = (char *) data;
aRule = (char *) malloc0(BUFFER_SIZE);
snprintf(aRule,BUFFER_SIZE,"%s\n",rule);
result = g_list_append(result,aRule);
}
// Loop with all the ruleset items
g_list_foreach(chain->ruleset,processRuleset,NULL);
}
aRule = (char *) malloc0(BUFFER_SIZE);
snprintf(aRule,BUFFER_SIZE,"*%s\n",tableName);
result = g_list_append(result,aRule);
// First generate chain names
g_hash_table_foreach(table->chains,processChains,NULL);
// Then the rules for the chains
g_hash_table_foreach(table->chains,processRules,NULL);
aRule = (char *) malloc0(BUFFER_SIZE);
snprintf(aRule,BUFFER_SIZE,"COMMIT\n");
result = g_list_append(result,aRule);
}
/* Don't test version, it displays a nasty error
LIBXML_TEST_VERSION
*/
// COMPAT: Do not genrate nodes for formatting spaces
xmlKeepBlanksDefault(0);
/* Check if file exists */
if (stat(filename,&fstat) != 0)
{
fprintf(stderr,"ERROR: Failed to stat configuration path \"%s\": %s",filename,strerror(errno));
return NULL;
}
else
if (!S_ISREG(fstat.st_mode))
{
fprintf(stderr,"ERROR: Specified configuration path \"%s\" is not a regular file",filename);
return NULL;
}
// Build an XML tree from a the file
doc = xmlParseFile(filename);
if (doc == NULL)
return(NULL);
// Check the document is of the right kind
cur = xmlDocGetRootElement(doc);
if (cur == NULL)
{
fprintf(stderr,"ERROR: Empty document\n");
xmlFreeDoc(doc);
return(NULL);
}
// Check if we have the right root element & block
if (xmlStrcmp(cur->name, (const xmlChar *) "firewall"))
{
fprintf(stderr,"ERROR: Document of the wrong type, root node != firewall");
xmlFreeDoc(doc);
return(NULL);
}
// Init everything...
fwHash = g_hash_table_new(g_str_hash,g_str_equal);
i = 0;
tableName = tableList[i];
while (tableName)
{
// See if we have a table by this name
tmpTable = lookupTable(fwHash,tableName);
// Check if we already did the chain or not
aChain = lookupChain(tmpTable->chains,"INPUT");
aChain->defaultTarget = "ACCEPT";
aChain = lookupChain(tmpTable->chains,"FORWARD");
aChain->defaultTarget = "ACCEPT";
aChain = lookupChain(tmpTable->chains,"OUTPUT");
aChain->defaultTarget = "ACCEPT";
// Advance...
i++;
tableName = tableList[i];
}
// Walk the tree.
cur = cur->xmlChildrenNode;
while (cur)
{
// Try find sections
if (!xmlStrcmp(cur->name, (const xmlChar *) "global"))
classHash = parseGlobal(doc,cur);
else if (!xmlStrcmp(cur->name, (const xmlChar *) "acl"))
parseACL(doc,cur,fwHash,classHash);
else if (!xmlStrcmp(cur->name, (const xmlChar *) "nat"))
parseNAT(doc,cur,fwHash,classHash);
else if (!xmlStrcmp(cur->name, (const xmlChar *) "traffic"))
parseTraffic(doc,cur,fwHash,classHash);
// Make sure this isn't a comment
else if (xmlStrcmp(cur->name, (const xmlChar *) "text"))
fprintf(stderr,"ERROR: Section <%s> not recognised, ignoring",cur->name);
// Next plz!!
cur = cur->next;
}
// Clean up everything else before quitting.
xmlCleanupParser();
/* Check if we appending zero counters */
if (resetCounters)
sprintf(counters,"%s"," [0:0]");
// Build rule list
g_hash_table_foreach(fwHash,processTable,NULL);
return(result);
}
// Function to write firewall to file
static int writeFirewall(GList *ruleList, char *filename, char load)
{
int fd;
int fuct = 0;
char *buffer, datetime[32];
FILE *piptables_restore = NULL;
// Process rule by rule & write to file and/or pipe to iptables directly
void writeRule(gpointer data, gpointer user_data)
{
int res;
if (!fuct)
{
// Write to file...
res = write(fd,data,strlen(data));
if (res < 0)
{
fprintf(stderr,"Failed to write to file: %s\n",strerror(errno));
fuct = 1;
}
// Check if we piping to iptables aswell
if (piptables_restore)
{
fprintf(piptables_restore, "%s", (char *) data);
// Check for IO error
if (ferror(piptables_restore))
{
fprintf(stderr,"Failed to write to file: %s\n",strerror(errno));
piptables_restore = NULL;
}
}
}
}
// Open firewall file
fd = open(filename,O_CREAT|O_TRUNC|O_WRONLY,S_IREAD|S_IWRITE);
if (fd < 0)
{
fprintf(stderr,"Failed to open file \"%s\": %s\n",filename,strerror(errno));
return(-1);
}
// Check if we piping direct to iptables aswell
if (load)
{
// iptables-restore should be in path
piptables_restore = popen("iptables-restore", "w");
if (!piptables_restore)
fprintf(stderr, "ERROR: Can not find iptables-restore in $PATH, skipping load\n");
printf("Loading firewall configuration directly into kernel...\n");
}
buffer = (char *) malloc0(BUFFER_SIZE);
// Write out comment to say what version & at what datetime we generated the firewall
snprintf(buffer,BUFFER_SIZE,"# Generated using BWM Firewall v%s: %s\n",PACKAGE_VERSION,
date2str((char *) &datetime));
write(fd,buffer,strlen(buffer));
// Loop with all rules
g_list_foreach(ruleList,writeRule,NULL);
// Finally close file descriptor
close(fd);
// If we opened iptables-restore close
if (piptables_restore)
fclose(piptables_restore);
return(fuct);
}
// Print out our usage
void printUsage(char **argv)
{
printf("Usage: %s <options>\n",argv[0]);
printf("\n");
printf("Options:\n");
printf(" -c, --config=<config_file> Specify non-default BWM Tools config file\n");
printf(" -f, --file[=<output_file>] Generate iptables-restore file from BWM Tools firewall\n");
printf(" -l, --load Load BWM Tools firewall directly into kernel\n");
printf(" -h, --help Display this page\n");
printf(" -r, --reset-counters Reset iptables counters, usable with \"iptables-restore -c\"\n");
printf("\n");
}
// Obviously we need our main function
int main (int argc, char **argv)
{
GList *fw;
int c;
char *configFile = CONFIG_FILE;
char *outputFile = IPTABLES_FILE;
char resetCounters = 0;
int res = 1; // signal we return error status
char writeFile = 0;
char loadFirewall = 0;
// Our options
struct option long_options[] =
{
{"config",required_argument,0,'c'},
{"file",optional_argument,0,'f'},
{"load",no_argument,0,'l'},
{"help",no_argument,0,'h'},
{"reset-counters",no_argument,0,'r'},
{0,0,0,0}
};
printf("BWM Firewall v%s - Copyright (c) 2003-2006 Linux Based Systems Design\n\n",PACKAGE_VERSION);
// Check if we have no args
if (argc == 1)
{
printUsage(argv);
return(1);
}
// Loop with options
while (1)
{
int option_index = 0;
// Process
c = getopt_long(argc,argv,"c:f::lhr",long_options,&option_index);
if (c == -1)
break;
// Check...
switch (c)
{
case 'c':
configFile = strdup(optarg);
break;
case 'f':
// If we have an option, save it
if (optarg)
outputFile = strdup(optarg);
writeFile = 1;
break;
case 'l':
loadFirewall = 1;
break;
case 'h':
printUsage(argv);
return(0);
case 'r':
resetCounters = 1;
break;
}
}
// Let us know about ahy unknown options
if (optind < argc)
{
while (optind < argc)
fprintf(stderr,"%s: invalid option -- %s\n",argv[0],argv[optind++]);
return 1;
}
// Check if we actually going to do anything
if (!writeFile && !loadFirewall)
{
printf("ERROR: No action to take\n");
printUsage(argv);
return 1;
}
// Load configuration
printf("Loading configuration from \"%s\"...\n",configFile);
fw = createFirewallRules(configFile,resetCounters);
// Write out firewall
if (fw)
{
printf("Processing firewall/shaping configuration...\n");
res = writeFirewall(fw,outputFile,loadFirewall);
}
// Return result code
return res;
}