mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-03-22 03:07:20 +01:00
794 lines
28 KiB
C++
794 lines
28 KiB
C++
/*
|
|
|
|
Firewall Builder
|
|
|
|
Copyright (C) 2009 NetCitadel, LLC
|
|
|
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
|
|
|
$Id$
|
|
|
|
This program is free software which we release under the GNU General Public
|
|
License. You may redistribute and/or modify this program under the terms
|
|
of that 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.
|
|
|
|
To get a copy of the GNU General Public License, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
#include "../../config.h"
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <stdexcept>
|
|
#include <memory>
|
|
|
|
#include <assert.h>
|
|
#include <cstring>
|
|
#include <iomanip>
|
|
|
|
#include "Configlet.h"
|
|
#include "CompilerDriver_pf.h"
|
|
|
|
#include "PolicyCompiler_pf.h"
|
|
#include "NATCompiler_pf.h"
|
|
#include "TableFactory.h"
|
|
#include "Preprocessor_pf.h"
|
|
#include "RoutingCompiler_openbsd.h"
|
|
#include "RoutingCompiler_freebsd.h"
|
|
|
|
#include "OSConfigurator_openbsd.h"
|
|
#include "OSConfigurator_freebsd.h"
|
|
#include "OSConfigurator_solaris.h"
|
|
|
|
#include "fwbuilder/Resources.h"
|
|
#include "fwbuilder/FWObjectDatabase.h"
|
|
#include "fwbuilder/XMLTools.h"
|
|
#include "fwbuilder/FWException.h"
|
|
#include "fwbuilder/Firewall.h"
|
|
#include "fwbuilder/Interface.h"
|
|
#include "fwbuilder/Policy.h"
|
|
#include "fwbuilder/NAT.h"
|
|
#include "fwbuilder/Routing.h"
|
|
|
|
#include "fwcompiler/Preprocessor.h"
|
|
#include "fwcompiler/exceptions.h"
|
|
|
|
#include "fwbuilder/Resources.h"
|
|
#include "fwbuilder/FWObjectDatabase.h"
|
|
#include "fwbuilder/FWException.h"
|
|
#include "fwbuilder/Cluster.h"
|
|
#include "fwbuilder/ClusterGroup.h"
|
|
#include "fwbuilder/Firewall.h"
|
|
#include "fwbuilder/Interface.h"
|
|
#include "fwbuilder/Policy.h"
|
|
#include "fwbuilder/StateSyncClusterGroup.h"
|
|
#include "fwbuilder/FailoverClusterGroup.h"
|
|
|
|
#include <QStringList>
|
|
#include <QFileInfo>
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include <QtDebug>
|
|
|
|
|
|
using namespace std;
|
|
using namespace libfwbuilder;
|
|
using namespace fwcompiler;
|
|
|
|
// #define DEBUG_FILE_NAMES 1
|
|
|
|
|
|
QString CompilerDriver_pf::composeActivationCommand(Firewall *fw,
|
|
const string &pfctl_debug,
|
|
const string &anchor_name,
|
|
const string &pf_version,
|
|
const string &remote_file_name)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
Configlet act(fw, "pf",
|
|
options->getBool("generate_rc_conf_file") ?
|
|
"rc_conf_activation" : "activation");
|
|
|
|
act.removeComments();
|
|
act.setVariable("pfctl_debug", pfctl_debug.c_str());
|
|
act.setVariable("anchor", !anchor_name.empty());
|
|
act.setVariable("anchor_name", anchor_name.c_str());
|
|
if (pf_version == "obsd_lt_3.2")
|
|
{
|
|
act.setVariable("pf_version_lt_3_2", 1);
|
|
act.setVariable("pf_version_ge_3_2", 0);
|
|
} else
|
|
{
|
|
act.setVariable("pf_version_lt_3_2", 0);
|
|
act.setVariable("pf_version_ge_3_2", 1);
|
|
}
|
|
act.setVariable("remote_file", remote_file_name.c_str());
|
|
return act.expand();
|
|
}
|
|
|
|
QString CompilerDriver_pf::printActivationCommands(Firewall *fw)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
bool debug = options->getBool("debug");
|
|
string pfctl_dbg = (debug)?"-v ":"";
|
|
|
|
QString remote_file_name = escapeFileName(remote_file_names[CONF1_FILE]);
|
|
|
|
return composeActivationCommand(
|
|
fw, pfctl_dbg, "",
|
|
fw->getStr("version"), remote_file_name.toUtf8().constData());
|
|
|
|
#if 0
|
|
QStringList activation_commands;
|
|
|
|
// skip first item in the list since it is .fw script
|
|
for(int idx=1; idx<file_names.size(); idx++)
|
|
{
|
|
QString remote_file_name = escapeFileName(remote_file_names[idx]);
|
|
|
|
activation_commands.push_back(
|
|
composeActivationCommand(
|
|
fw, pfctl_dbg, anchor_names[idx].toUtf8().constData(),
|
|
fw->getStr("version"), remote_file_name.toUtf8().constData()));
|
|
}
|
|
|
|
return activation_commands.join("\n");
|
|
#endif
|
|
}
|
|
|
|
QString CompilerDriver_pf::assembleManifest(Cluster*, Firewall* , bool )
|
|
{
|
|
QString script_buffer;
|
|
QTextStream script(&script_buffer, QIODevice::WriteOnly);
|
|
|
|
for(int idx=0; idx<file_names.size(); idx++)
|
|
{
|
|
QString master_file_marker = (idx==0) ? "* " : " ";
|
|
QString local_file_name = file_names[idx];
|
|
QString remote_file_name = remote_file_names[idx];
|
|
script << MANIFEST_MARKER << master_file_marker
|
|
<< escapeFileName(local_file_name);
|
|
if (!remote_file_name.isEmpty() && remote_file_name != local_file_name)
|
|
script << " " << escapeFileName(remote_file_name);
|
|
script << "\n";
|
|
}
|
|
|
|
return script_buffer;
|
|
}
|
|
|
|
QString CompilerDriver_pf::assembleFwScript(Cluster *cluster,
|
|
Firewall* fw,
|
|
bool cluster_member,
|
|
OSConfigurator *oscnf)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
|
|
Configlet script_skeleton(
|
|
fw, "pf",
|
|
options->getBool("generate_rc_conf_file") ?
|
|
"rc_conf_skeleton" : "script_skeleton");
|
|
|
|
Configlet top_comment(fw, "pf",
|
|
options->getBool("generate_rc_conf_file") ?
|
|
"rc_conf_top_comment" : "top_comment");
|
|
|
|
script_skeleton.setVariable("routing_script",
|
|
QString::fromUtf8(routing_script.c_str()));
|
|
|
|
assembleFwScriptInternal(
|
|
cluster, fw, cluster_member, oscnf,
|
|
&script_skeleton, &top_comment, "#",
|
|
!options->getBool("generate_rc_conf_file"));
|
|
|
|
if (fw->getStr("platform") == "pf")
|
|
{
|
|
script_skeleton.setVariable(
|
|
"pf_flush_states", options->getBool("pf_flush_states"));
|
|
script_skeleton.setVariable(
|
|
"pf_version_ge_4_x", // fw->getStr("version")=="4.x");
|
|
XMLTools::version_compare(fw->getStr("version"), "4.0")>=0);
|
|
|
|
} else
|
|
{
|
|
script_skeleton.setVariable("pf_flush_states", 0);
|
|
script_skeleton.setVariable("pf_version_ge_4_x", 0);
|
|
}
|
|
|
|
return script_skeleton.expand();
|
|
}
|
|
|
|
QString CompilerDriver_pf::run(const std::string &cluster_id,
|
|
const std::string &firewall_id,
|
|
const std::string &single_rule_id)
|
|
{
|
|
Cluster *cluster = NULL;
|
|
if (!cluster_id.empty())
|
|
cluster = Cluster::cast(
|
|
objdb->findInIndex(objdb->getIntId(cluster_id)));
|
|
|
|
Firewall *fw = Firewall::cast(
|
|
objdb->findInIndex(objdb->getIntId(firewall_id)));
|
|
assert(fw);
|
|
|
|
try
|
|
{
|
|
clearReadOnly(fw);
|
|
|
|
// Copy rules from the cluster object
|
|
populateClusterElements(cluster, fw);
|
|
|
|
commonChecks2(cluster, fw);
|
|
|
|
FWOptions* options = fw->getOptionsObject();
|
|
|
|
// Note that fwobjectname may be different from the name of the
|
|
// firewall fw This happens when we compile a member of a cluster
|
|
current_firewall_name = QString::fromUtf8(fw->getName().c_str());
|
|
|
|
string firewall_dir = options->getStr("firewall_dir");
|
|
if (firewall_dir=="") firewall_dir="/etc/fw";
|
|
|
|
string prolog_place = options->getStr("prolog_place");
|
|
if (prolog_place.empty()) prolog_place = "fw_file"; // old default
|
|
string pre_hook = fw->getOptionsObject()->getStr("prolog_script");
|
|
|
|
bool debug = options->getBool("debug");
|
|
string shell_dbg = (debug)?"set -x":"" ;
|
|
string pfctl_dbg = (debug)?"-v ":"";
|
|
|
|
|
|
/*
|
|
* Process firewall options, build OS network configuration script
|
|
*/
|
|
std::auto_ptr<OSConfigurator_bsd> oscnf;
|
|
string platform = fw->getStr("platform");
|
|
string fw_version = fw->getStr("version");
|
|
string host_os = fw->getStr("host_OS");
|
|
string family = Resources::os_res[host_os]->
|
|
Resources::getResourceStr("/FWBuilderResources/Target/family");
|
|
|
|
if (host_os == "solaris")
|
|
oscnf = std::auto_ptr<OSConfigurator_bsd>(new OSConfigurator_solaris(
|
|
objdb , fw, false));
|
|
|
|
if (host_os == "openbsd")
|
|
oscnf = std::auto_ptr<OSConfigurator_bsd>(new OSConfigurator_openbsd(
|
|
objdb , fw, false));
|
|
|
|
if (host_os == "freebsd")
|
|
oscnf = std::auto_ptr<OSConfigurator_bsd>(new OSConfigurator_freebsd(
|
|
objdb , fw, false));
|
|
|
|
if (oscnf.get()==NULL)
|
|
{
|
|
abort("Unrecognized host OS " + host_os + " (family " + family + ")");
|
|
return "";
|
|
}
|
|
|
|
oscnf->prolog();
|
|
|
|
QString remote_fw_name = QString::fromUtf8(
|
|
options->getStr("script_name_on_firewall").c_str());
|
|
QString remote_conf_name = QString::fromUtf8(
|
|
options->getStr("conf_file_name_on_firewall").c_str());
|
|
|
|
list<FWObject*> all_policies = fw->getByType(Policy::TYPENAME);
|
|
list<FWObject*> all_nat = fw->getByType(NAT::TYPENAME);
|
|
|
|
findImportedRuleSets(fw, all_policies);
|
|
findImportedRuleSets(fw, all_nat);
|
|
|
|
list<FWObject*> all_rulesets;
|
|
all_rulesets.insert(
|
|
all_rulesets.begin(), all_policies.begin(), all_policies.end());
|
|
all_rulesets.insert(
|
|
all_rulesets.begin(), all_nat.begin(), all_nat.end());
|
|
|
|
// establish mapping of rule sets to file names so it can be used
|
|
// for "load anchor" commands
|
|
|
|
QMap<QString, QString> rulesets_to_file_names;
|
|
QMap<QString, QString> rulesets_to_remote_file_names;
|
|
QMap<QString, int> rulesets_to_indexes;
|
|
QStringList file_extensions;
|
|
QStringList remote_file_options;
|
|
|
|
anchor_names.clear();
|
|
|
|
anchor_names << ""; // for fw_file
|
|
anchor_names << ""; // for main .conf file (both policy and nat top rule sets)
|
|
|
|
// Can not make extension .conf when generating rc.conf file
|
|
// because the second file also has extension .conf and this
|
|
// causes conflict if both names are generated using default
|
|
// algorithm from the fw name
|
|
//
|
|
|
|
file_extensions << "fw";
|
|
file_extensions << "conf";
|
|
|
|
remote_file_options << "script_name_on_firewall";
|
|
remote_file_options << "conf_file_name_on_firewall";
|
|
|
|
rulesets_to_indexes["__main__"] = CONF1_FILE;
|
|
|
|
int idx = CONF2_FILE;
|
|
for (list<FWObject*>::iterator p=all_rulesets.begin();
|
|
p!=all_rulesets.end(); ++p)
|
|
{
|
|
RuleSet *rs = RuleSet::cast(*p);
|
|
QString ruleset_name = QString::fromUtf8(rs->getName().c_str());
|
|
|
|
if (ruleset_name.endsWith("/*"))
|
|
{
|
|
QString err("The name of the %1 ruleset %2"
|
|
" ends with '/*', assuming it is externally"
|
|
" controlled and skipping it.");
|
|
warning(fw, rs, NULL,
|
|
err.arg(rs->getTypeName().c_str())
|
|
.arg(ruleset_name).toStdString());
|
|
rs->setBool(".skip_ruleset", true);
|
|
continue;
|
|
}
|
|
|
|
if (rs->isTop()) continue;
|
|
|
|
// record index of this ruleset in file_names and remote_file_names
|
|
if (rulesets_to_indexes.count(ruleset_name) == 0)
|
|
{
|
|
anchor_names << ruleset_name;
|
|
file_extensions << "conf";
|
|
remote_file_options << ""; // to make sure it has right number of items
|
|
rulesets_to_indexes[ruleset_name] = idx;
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG_FILE_NAMES
|
|
qDebug() << "anchor_names=" << anchor_names;
|
|
qDebug() << "file_extensions=" << file_extensions;
|
|
qDebug() << "remote_file_options=" << remote_file_options;
|
|
#endif
|
|
|
|
// The order of file names in file_names and remote_file_names
|
|
// is the same as the order of rule sets in all_rulesets
|
|
determineOutputFileNames(cluster, fw, !cluster_id.empty(),
|
|
anchor_names, file_extensions,
|
|
remote_file_options);
|
|
|
|
|
|
for (list<FWObject*>::iterator p=all_rulesets.begin();
|
|
p!=all_rulesets.end(); ++p)
|
|
{
|
|
RuleSet *rs = RuleSet::cast(*p);
|
|
if (rs->getBool(".skip_ruleset")) continue;
|
|
QString ruleset_name = QString::fromUtf8(rs->getName().c_str());
|
|
if (rs->isTop()) ruleset_name = "__main__";
|
|
int idx = rulesets_to_indexes[ruleset_name];
|
|
rulesets_to_file_names[ruleset_name] = file_names[idx];
|
|
rulesets_to_remote_file_names[ruleset_name] = remote_file_names[idx];
|
|
}
|
|
|
|
#ifdef DEBUG_FILE_NAMES
|
|
qDebug() << "file_names=" << file_names;
|
|
qDebug() << "remote_file_names=" << remote_file_names;
|
|
qDebug() << "rulesets_to_file_names=" << rulesets_to_file_names;
|
|
qDebug() << "rulesets_to_remote_file_names=" << rulesets_to_remote_file_names;
|
|
#endif
|
|
|
|
int routing_rules_count = 0;
|
|
|
|
vector<int> ipv4_6_runs;
|
|
|
|
// command line options -4 and -6 control address family for which
|
|
// script will be generated. If "-4" is used, only ipv4 part will
|
|
// be generated. If "-6" is used, only ipv6 part will be generated.
|
|
// If neither is used, both parts will be done.
|
|
|
|
if (options->getStr("ipv4_6_order").empty() ||
|
|
options->getStr("ipv4_6_order") == "ipv4_first")
|
|
{
|
|
if (ipv4_run) ipv4_6_runs.push_back(AF_INET);
|
|
if (ipv6_run) ipv4_6_runs.push_back(AF_INET6);
|
|
}
|
|
|
|
if (options->getStr("ipv4_6_order") == "ipv6_first")
|
|
{
|
|
if (ipv6_run) ipv4_6_runs.push_back(AF_INET6);
|
|
if (ipv4_run) ipv4_6_runs.push_back(AF_INET);
|
|
}
|
|
|
|
ostringstream* main_str = new ostringstream();
|
|
|
|
for (vector<int>::iterator i=ipv4_6_runs.begin();
|
|
i!=ipv4_6_runs.end(); ++i)
|
|
{
|
|
int policy_af = *i;
|
|
bool ipv6_policy = (policy_af == AF_INET6);
|
|
|
|
// Count rules for each address family
|
|
int nat_count = 0;
|
|
int policy_count = 0;
|
|
|
|
for (list<FWObject*>::iterator p=all_nat.begin();
|
|
p!=all_nat.end(); ++p)
|
|
{
|
|
NAT *nat = NAT::cast(*p);
|
|
if (nat->matchingAddressFamily(policy_af)) nat_count++;
|
|
}
|
|
|
|
for (list<FWObject*>::iterator p=all_policies.begin();
|
|
p!=all_policies.end(); ++p)
|
|
{
|
|
Policy *policy = Policy::cast(*p);
|
|
if (policy->matchingAddressFamily(policy_af)) policy_count++;
|
|
}
|
|
|
|
if (nat_count || policy_count)
|
|
{
|
|
Preprocessor_pf* prep = new Preprocessor_pf(
|
|
objdb , fw, ipv6_policy);
|
|
if (inTestMode()) prep->setTestMode();
|
|
if (inEmbeddedMode()) prep->setEmbeddedMode();
|
|
prep->compile();
|
|
delete prep;
|
|
}
|
|
|
|
list<NATCompiler_pf::redirectRuleInfo> redirect_rules_info;
|
|
|
|
for (list<FWObject*>::iterator p=all_nat.begin();
|
|
p!=all_nat.end(); ++p )
|
|
{
|
|
NAT *nat = NAT::cast(*p);
|
|
|
|
if (!nat->matchingAddressFamily(policy_af)) continue;
|
|
if (nat->getBool(".skip_ruleset")) continue;
|
|
|
|
QString ruleset_name = QString::fromUtf8(nat->getName().c_str());
|
|
if (nat->isTop()) ruleset_name = "__main__";
|
|
|
|
if (table_factories.count(ruleset_name) == 0)
|
|
{
|
|
table_factories[ruleset_name] = new fwcompiler::TableFactory(this);
|
|
}
|
|
|
|
NATCompiler_pf n( objdb, fw, ipv6_policy, oscnf.get(),
|
|
table_factories[ruleset_name]
|
|
);
|
|
|
|
n.setSourceRuleSet( nat );
|
|
n.setRuleSetName(nat->getName());
|
|
|
|
n.setSingleRuleCompileMode(single_rule_id);
|
|
n.setDebugLevel( dl );
|
|
if (rule_debug_on) n.setDebugRule(drn);
|
|
n.setVerbose( verbose );
|
|
if (inTestMode()) n.setTestMode();
|
|
if (inEmbeddedMode()) n.setEmbeddedMode();
|
|
|
|
int nat_rules_count = 0;
|
|
if ( (nat_rules_count=n.prolog()) > 0 )
|
|
{
|
|
n.compile();
|
|
n.epilog();
|
|
}
|
|
have_nat = (have_nat || (nat_rules_count > 0));
|
|
|
|
if (nat->isTop())
|
|
{
|
|
generated_scripts[ruleset_name] = main_str;
|
|
} else
|
|
{
|
|
generated_scripts[ruleset_name] = new ostringstream();
|
|
}
|
|
|
|
if (n.getCompiledScriptLength() > 0)
|
|
{
|
|
if (n.haveErrorsAndWarnings())
|
|
{
|
|
// store errors and warnings so they will appear on top
|
|
// of .fw file in addition to the .conf file
|
|
if (!single_rule_compile_on)
|
|
{
|
|
*(generated_scripts[ruleset_name])
|
|
<< "# NAT compiler errors and warnings:"
|
|
<< endl;
|
|
*(generated_scripts[ruleset_name]) << n.getErrors("# ");
|
|
}
|
|
}
|
|
*(generated_scripts[ruleset_name]) << n.getCompiledScript();
|
|
*(generated_scripts[ruleset_name]) << endl;
|
|
}
|
|
|
|
all_errors.push_back(n.getErrors("").c_str());
|
|
|
|
const list<NATCompiler_pf::redirectRuleInfo> lst =
|
|
n.getRedirRulesInfo();
|
|
redirect_rules_info.insert(redirect_rules_info.begin(),
|
|
lst.begin(), lst.end());
|
|
}
|
|
|
|
|
|
for (list<FWObject*>::iterator p=all_policies.begin();
|
|
p!=all_policies.end(); ++p )
|
|
{
|
|
Policy *policy = Policy::cast(*p);
|
|
|
|
if (!policy->matchingAddressFamily(policy_af)) continue;
|
|
if (policy->getBool(".skip_ruleset")) continue;
|
|
|
|
QString ruleset_name = QString::fromUtf8(policy->getName().c_str());
|
|
if (policy->isTop()) ruleset_name = "__main__";
|
|
|
|
if (table_factories.count(ruleset_name) == 0)
|
|
{
|
|
table_factories[ruleset_name] = new fwcompiler::TableFactory(this);
|
|
}
|
|
|
|
PolicyCompiler_pf c( objdb, fw, ipv6_policy, oscnf.get(),
|
|
&redirect_rules_info,
|
|
table_factories[ruleset_name]
|
|
);
|
|
|
|
c.setSourceRuleSet( policy );
|
|
c.setRuleSetName(policy->getName());
|
|
|
|
c.setSingleRuleCompileMode(single_rule_id);
|
|
c.setDebugLevel( dl );
|
|
if (rule_debug_on) c.setDebugRule(drp);
|
|
c.setVerbose( verbose );
|
|
if (inTestMode()) c.setTestMode();
|
|
if (inEmbeddedMode()) c.setEmbeddedMode();
|
|
|
|
int pf_rules_count = 0;
|
|
if ( (pf_rules_count=c.prolog()) > 0 )
|
|
{
|
|
c.compile();
|
|
c.epilog();
|
|
}
|
|
have_filter = (have_filter || (pf_rules_count > 0));
|
|
|
|
if (policy->isTop())
|
|
{
|
|
generated_scripts["__main__"] = main_str;
|
|
} else
|
|
{
|
|
generated_scripts[ruleset_name] = new ostringstream();
|
|
}
|
|
|
|
if (c.getCompiledScriptLength() > 0)
|
|
{
|
|
if (c.haveErrorsAndWarnings())
|
|
{
|
|
if (!single_rule_compile_on)
|
|
{
|
|
*(generated_scripts[ruleset_name])
|
|
<< "# Policy compiler errors and warnings:"
|
|
<< endl;
|
|
*(generated_scripts[ruleset_name]) << c.getErrors("# ");
|
|
}
|
|
}
|
|
*(generated_scripts[ruleset_name]) << c.getCompiledScript();
|
|
*(generated_scripts[ruleset_name]) << endl;
|
|
}
|
|
|
|
all_errors.push_back(c.getErrors("").c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::auto_ptr<RoutingCompiler> routing_compiler;
|
|
|
|
if (host_os == "openbsd")
|
|
routing_compiler = std::auto_ptr<RoutingCompiler>(
|
|
new RoutingCompiler_openbsd(objdb, fw, false, oscnf.get()));
|
|
|
|
if (host_os == "freebsd")
|
|
routing_compiler = std::auto_ptr<RoutingCompiler>(
|
|
new RoutingCompiler_freebsd(objdb, fw, false, oscnf.get()));
|
|
|
|
if (routing_compiler.get() == NULL)
|
|
{
|
|
abort("Unrecognized host OS " + host_os + " (family " + family + ")");
|
|
return "";
|
|
}
|
|
|
|
RuleSet *routing = RuleSet::cast(fw->getFirstByType(Routing::TYPENAME));
|
|
if (routing)
|
|
{
|
|
routing_compiler->setSourceRuleSet(routing);
|
|
routing_compiler->setRuleSetName(routing->getName());
|
|
|
|
routing_compiler->setSingleRuleCompileMode(single_rule_id);
|
|
routing_compiler->setDebugLevel( dl );
|
|
if (rule_debug_on) routing_compiler->setDebugRule(drp);
|
|
routing_compiler->setVerbose( verbose );
|
|
if (inTestMode()) routing_compiler->setTestMode();
|
|
if (inEmbeddedMode()) routing_compiler->setEmbeddedMode();
|
|
|
|
if ( (routing_rules_count=routing_compiler->prolog()) > 0 )
|
|
{
|
|
routing_compiler->compile();
|
|
routing_compiler->epilog();
|
|
}
|
|
|
|
if (routing_compiler->haveErrorsAndWarnings())
|
|
all_errors.push_back(routing_compiler->getErrors("").c_str());
|
|
|
|
routing_script += routing_compiler->getCompiledScript();
|
|
}
|
|
|
|
|
|
if (haveErrorsAndWarnings())
|
|
{
|
|
all_errors.push_front(getErrors("").c_str());
|
|
}
|
|
|
|
if (single_rule_compile_on)
|
|
{
|
|
// in single rule compile mode just return the result
|
|
QString buffer;
|
|
QTextStream pf_str(&buffer);
|
|
|
|
for (map<QString, ostringstream*>::iterator fi=generated_scripts.begin();
|
|
fi!=generated_scripts.end(); fi++)
|
|
{
|
|
QString ruleset_name = fi->first;
|
|
ostringstream *strm = fi->second;
|
|
pf_str << table_factories[ruleset_name]->PrintTables();
|
|
pf_str << QString::fromUtf8(strm->str().c_str());
|
|
pf_str << QString::fromUtf8(routing_script.c_str());
|
|
}
|
|
|
|
// clear() calls destructors of all elements in the container
|
|
table_factories.clear();
|
|
generated_scripts.clear();
|
|
|
|
return formSingleRuleCompileOutput(buffer);
|
|
}
|
|
|
|
/* add commands to load anchors to the bottom of the main .conf file */
|
|
QMap<QString, QString>::iterator it;
|
|
for (it=rulesets_to_remote_file_names.begin();
|
|
it!=rulesets_to_remote_file_names.end(); ++it)
|
|
{
|
|
QString ruleset_name = it.key();
|
|
if (ruleset_name == "__main__") continue;
|
|
QString remote_file_name = it.value();
|
|
*(generated_scripts["__main__"]) << QString("load anchor %1 from \"%2\"")
|
|
.arg(ruleset_name).arg(remote_file_name).toUtf8().constData()
|
|
<< endl;
|
|
}
|
|
|
|
|
|
/*
|
|
* now write generated scripts to files
|
|
*/
|
|
|
|
idx = CONF1_FILE;
|
|
for (map<QString, ostringstream*>::iterator fi=generated_scripts.begin();
|
|
fi!=generated_scripts.end(); fi++)
|
|
{
|
|
QString ruleset_name = fi->first;
|
|
QString file_name = rulesets_to_file_names[ruleset_name]; // file_names[idx];
|
|
ostringstream *strm = fi->second;
|
|
|
|
if (ruleset_name.contains("/*")) continue;
|
|
|
|
file_name = getAbsOutputFileName(file_name);
|
|
|
|
info("Output file name: " + file_name.toStdString());
|
|
QFile pf_file(file_name);
|
|
if (pf_file.open(QIODevice::WriteOnly))
|
|
{
|
|
QTextStream pf_str(&pf_file);
|
|
|
|
if (ruleset_name == "__main__")
|
|
{
|
|
printStaticOptions(pf_str, fw);
|
|
pf_str << table_factories[ruleset_name]->PrintTables();
|
|
if (prolog_place == "pf_file_after_tables")
|
|
printProlog(pf_str, pre_hook);
|
|
} else
|
|
{
|
|
pf_str << table_factories[ruleset_name]->PrintTables();
|
|
}
|
|
|
|
pf_str << QString::fromUtf8(strm->str().c_str());
|
|
pf_file.close();
|
|
} else
|
|
{
|
|
// clear() calls destructors of all elements in the container
|
|
table_factories.clear();
|
|
generated_scripts.clear();
|
|
|
|
QString err("Failed to open file %1 for writing: %2; "
|
|
"Current dir: %3");
|
|
abort(err.arg(pf_file.fileName())
|
|
.arg(pf_file.error())
|
|
.arg(QDir::current().path()).toStdString());
|
|
}
|
|
|
|
idx++;
|
|
}
|
|
/*
|
|
* assemble the script and then perhaps post-process it if needed
|
|
*/
|
|
QString script_buffer = assembleFwScript(
|
|
cluster, fw, !cluster_id.empty(), oscnf.get());
|
|
|
|
// clear() calls destructors of all elements in the container
|
|
table_factories.clear();
|
|
generated_scripts.clear();
|
|
|
|
|
|
file_names[FW_FILE] = getAbsOutputFileName(file_names[FW_FILE]);
|
|
|
|
info("Output file name: " + file_names[FW_FILE].toStdString());
|
|
QFile fw_file(file_names[FW_FILE]);
|
|
if (fw_file.open(QIODevice::WriteOnly))
|
|
{
|
|
QTextStream fw_str(&fw_file);
|
|
fw_str << script_buffer;
|
|
fw_file.close();
|
|
fw_file.setPermissions(QFile::ReadOwner | QFile::WriteOwner |
|
|
QFile::ReadGroup | QFile::ReadOther |
|
|
QFile::ExeOwner |
|
|
QFile::ExeGroup |
|
|
QFile::ExeOther );
|
|
|
|
info(" Compiled successfully");
|
|
} else
|
|
{
|
|
QString err(" Failed to open file %1 for writing: %2; Current dir: %3");
|
|
abort(err.arg(fw_file.fileName())
|
|
.arg(fw_file.error()).arg(QDir::current().path()).toStdString());
|
|
}
|
|
}
|
|
catch (FWException &ex)
|
|
{
|
|
status = BaseCompiler::ERROR;
|
|
return QString::fromUtf8(ex.toString().c_str());
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
MapOstringStream::~MapOstringStream()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void MapOstringStream::clear()
|
|
{
|
|
std::map<QString, std::ostringstream*>::iterator it;
|
|
for (it=begin(); it!=end(); ++it)
|
|
delete it->second;
|
|
std::map<QString, std::ostringstream*>::clear();
|
|
}
|
|
|
|
MapTableFactory::~MapTableFactory()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void MapTableFactory::clear()
|
|
{
|
|
std::map<QString, fwcompiler::TableFactory*>::iterator it;
|
|
for (it=begin(); it!=end(); ++it)
|
|
delete it->second;
|
|
std::map<QString, fwcompiler::TableFactory*>::clear();
|
|
}
|
|
|