1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-25 04:37:22 +01:00
fwbuilder/src/iptlib/PolicyCompiler_PrintRule.cpp
Vadim Kurland 493d22fd1c 2009-12-14 vadim <vadim@vk.crocodile.org>
* src/res/configlets/linux24/automatic_rules: Generation of the
automatic rules (matching ESTABLISHED and INVALID states,
backup ssh access and others) now uses configlet. Fixes #883

* src/res/configlets/linux24/automatic_rules: generated script can
now include automatic rules to match IPv6 neighbor discovery ICMP6
packets. This is controlled by a checkbox in the iptables
"advanced" settings dialog and is off by default. Fixes #878
2009-12-15 00:15:58 +00:00

1708 lines
53 KiB
C++

/*
Firewall Builder
Copyright (C) 2002 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 "PolicyCompiler_ipt.h"
#include "OSConfigurator_linux24.h"
#include "fwbuilder/RuleElement.h"
#include "fwbuilder/IPService.h"
#include "fwbuilder/ICMPService.h"
#include "fwbuilder/ICMP6Service.h"
#include "fwbuilder/TCPService.h"
#include "fwbuilder/UDPService.h"
#include "fwbuilder/CustomService.h"
#include "fwbuilder/TagService.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/Network.h"
#include "fwbuilder/DNSName.h"
#include "fwbuilder/AddressRange.h"
#include "fwbuilder/FWObjectDatabase.h"
#include "fwbuilder/RuleElement.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/Interface.h"
#include "fwbuilder/IPv4.h"
#include "fwbuilder/Firewall.h"
#include "fwbuilder/Resources.h"
#include "fwbuilder/AddressTable.h"
#include "fwbuilder/UserService.h"
#include "fwbuilder/Inet6AddrMask.h"
#include "combinedAddress.h"
#include "Configlet.h"
#include <QStringList>
#include <iostream>
#if __GNUC__ > 3 || \
(__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || (__GNUC_MINOR__ == 2 ) ) ) || \
_MSC_VER
# include <streambuf>
#else
# include <streambuf.h>
#endif
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cstring>
#include <algorithm>
#include <assert.h>
using namespace libfwbuilder;
using namespace fwcompiler;
using namespace std;
/**
*-----------------------------------------------------------------------
* Methods for printing
*/
/*
* Prints single --option with argument and negation "!"
* taking into account the change that happened in iptables 1.4.3.1
* that causes warning
* Using intrapositioned negation (`--option ! this`) is deprecated in favor of extrapositioned (`! --option this`).
*/
string PolicyCompiler_ipt::PrintRule::_printSingleOptionWithNegation(
const string &option, RuleElement *rel, const string &arg)
{
ostringstream ostr;
if (XMLTools::version_compare(version, "1.4.3")>=0)
{
ostr << _printSingleObjectNegation(rel);
ostr << option << " ";
ostr << arg << " ";
} else
{
ostr << option << " ";
ostr << _printSingleObjectNegation(rel);
ostr << arg << " ";
}
return ostr.str();
}
void PolicyCompiler_ipt::PrintRule::initializeMinusNTracker()
{
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
for (list<string>::const_iterator i =
PolicyCompiler_ipt::getStandardChains().begin();
i != PolicyCompiler_ipt::getStandardChains().end(); ++i)
{
(*(ipt_comp->minus_n_commands))[*i] = true;
}
minus_n_tracker_initialized = true;
}
/*
* check and create new chain if needed
*/
string PolicyCompiler_ipt::PrintRule::_createChain(const string &chain)
{
string res;
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
if (!minus_n_tracker_initialized) initializeMinusNTracker();
if ( ipt_comp->minus_n_commands->count(chain)==0 )
{
res = string((ipt_comp->ipv6) ? "$IP6TABLES -N " : "$IPTABLES -N ") +
chain;
if (ipt_comp->my_table != "filter") res += " -t " + ipt_comp->my_table;
res += "\n";
(*(ipt_comp->minus_n_commands))[chain] = true;
}
return res;
}
string PolicyCompiler_ipt::PrintRule::_startRuleLine()
{
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
string res = (ipt_comp->ipv6) ? "$IP6TABLES " : "$IPTABLES ";
if (ipt_comp->my_table != "filter") res += "-t " + ipt_comp->my_table + " ";
res += "-A ";
return res;
}
string PolicyCompiler_ipt::PrintRule::_endRuleLine()
{
return string("\n");
}
string PolicyCompiler_ipt::PrintRule::_printRuleLabel(PolicyRule *rule)
{
ostringstream res;
bool nocomm = Resources::os_res[compiler->fw->getStr("host_OS")]->
Resources::getResourceBool(
"/FWBuilderResources/Target/options/suppress_comments");
string rl=rule->getLabel();
if (rl != current_rule_label)
{
if (!compiler->inSingleRuleCompileMode())
{
if (!nocomm)
{
res << "# " << endl;
res << "# Rule " << rl << endl;
res << "# " << endl;
}
res << "echo " << _quote(string("Rule ")+rl) << endl;
res << "# " << endl;
}
/* do not put comment in the script if it is intended for linksys */
if (!nocomm || compiler->inSingleRuleCompileMode())
{
string comm = rule->getComment();
if (!comm.empty())
{
string::size_type c1,c2;
c1=0;
while ( (c2=comm.find('\n',c1))!=string::npos )
{
res << "# " << comm.substr(c1,c2-c1) << endl;
c1=c2+1;
}
res << "# " << comm.substr(c1) << endl;
res << "# " << endl;
}
}
}
current_rule_label=rl;
string err = rule->getStr(".error_msg");
if (!err.empty()) res << "# " << err << endl;
return res.str();
}
/**
*-----------------------------------------------------------------------
*/
string PolicyCompiler_ipt::PrintRule::_printChain(PolicyRule *rule)
{
string s = rule->getStr("ipt_chain");
if (s.empty()) s = "UNKNOWN";
// check chain name length per bug report #2507239
if (s.length() > 30)
{
ostringstream str;
str << "Chain name '" << s << "' ";
str << "is longer than 30 characters. Rule " << rule->getLabel();
compiler->abort(rule, str.str());
}
s= s + " ";
return s;
}
string PolicyCompiler_ipt::PrintRule::_printModules(PolicyRule *rule)
{
std::ostringstream ostr;
string target=rule->getStr("ipt_target");
if (target.empty()) target="UNKNOWN";
FWOptions *ruleopt =rule->getOptionsObject();
int lim = 0;
/*
* Here is what do we do with limits:
*
* Limit set globally in 'Firewall' tab of the firewall dialog
* applies only to logging
*
* Limit set in the rule options dialog applies only to this
* rule's target.
*
* this is so as of 1.0.11 ( 28/06/03 ) --vk
*/
if (target=="LOG")
{
FWOptions *compopt=compiler->getCachedFwOpt();
if ((lim=compopt->getInt("limit_value"))>0)
{
ostr << " -m limit --limit " << lim;
string ls=compopt->getStr("limit_suffix");
if (!ls.empty()) ostr << ls;
int lb=compopt->getInt("limit_burst");
if (lb>0) ostr << " --limit-burst " << lb;
}
} else {
if (ruleopt!=NULL && (lim=ruleopt->getInt("limit_value"))>0)
{
ostr << " -m limit --limit " << lim;
string ls=ruleopt->getStr("limit_suffix");
if (!ls.empty()) ostr << ls;
int lb=ruleopt->getInt("limit_burst");
if (lb>0) ostr << " --limit-burst " << lb;
}
}
if (ruleopt!=NULL && (lim=ruleopt->getInt("connlimit_value"))>0)
{
ostr << " -m connlimit --connlimit-above " << lim;
int ml=ruleopt->getInt("connlimit_masklen");
if (ml>0) ostr << " --connlimit-mask " << ml;
}
if (ruleopt!=NULL && (lim=ruleopt->getInt("hashlimit_value"))>0)
{
string module_name = "hashlimit";
if (ruleopt->getBool("hashlimit_dstlimit"))
module_name = "dstlimit";
ostr << " -m " << module_name << " --" << module_name << " " << lim;
string ls = ruleopt->getStr("hashlimit_suffix");
if (!ls.empty()) ostr << ls;
int lb=ruleopt->getInt("hashlimit_burst");
if (lb>0) ostr << " --" << module_name << "-burst " << lb;
ls = ruleopt->getStr("hashlimit_mode");
if (ls.empty())
{
/* syntax "--hashlimit-mode srcip,srcport " (i.e. with options
separated by commas) tested with iptables 1.3.6
*/
QStringList opts;
bool f;
f = ruleopt->getBool("hashlimit_mode_srcip");
if (f) opts.push_back("srcip");
f = ruleopt->getBool("hashlimit_mode_dstip");
if (f) opts.push_back("dstip");
f = ruleopt->getBool("hashlimit_mode_srcport");
if (f) opts.push_back("srcport");
f = ruleopt->getBool("hashlimit_mode_dstport");
if (f) opts.push_back("dstport");
if (!opts.isEmpty())
ostr << " --" << module_name << "-mode " << opts.join(",").toStdString();
} else
// hashlimit_mode is v2.1 option. In v3 we have options
// hashlimit_mode_srcip
// hashlimit_mode_dstip
// hashlimit_mode_srcport
// hashlimit_mode_dstport
ostr << " --" << module_name << "-mode " << ls;
string hl_name = ruleopt->getStr("hashlimit_name");
if (hl_name.empty())
{
std::ostringstream hn;
hn << "htable_rule_" << rule->getPosition();
hl_name = hn.str();
}
ostr << " --" << module_name << "-name " << hl_name;
int arg = ruleopt->getInt("hashlimit_size");
if (arg>0) ostr << " --" << module_name << "-htable-size " << arg;
arg = ruleopt->getInt("hashlimit_max");
if (arg>0) ostr << " --" << module_name << "-htable-max " << arg;
arg = ruleopt->getInt("hashlimit_expire");
if (arg>0) ostr << " --" << module_name << "-htable-expire " << arg;
arg = ruleopt->getInt("hashlimit_gcinterval");
if (arg>0) ostr << " --" << module_name << "-htable-gcinterval " << arg;
}
return ostr.str();
}
string PolicyCompiler_ipt::PrintRule::_printTarget(PolicyRule *rule)
{
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
std::ostringstream ostr;
string target=rule->getStr("ipt_target");
if (target.empty()) target="UNKNOWN";
FWOptions *ruleopt =rule->getOptionsObject();
if (target=="CUSTOM")
{
ostr << ruleopt->getStr("custom_str");
return ostr.str();
}
// there is no ULOG for ip6tables yet
if (!ipt_comp->ipv6 && compiler->getCachedFwOpt()->getBool("use_ULOG") &&
target=="LOG") target="ULOG";
ostr << " -j " << target << " ";
if (target=="REJECT")
ostr << _printActionOnReject(rule);
if (target=="LOG" || target=="ULOG")
ostr << _printLogParameters(rule);
if (target=="MARK")
{
// ostr << " --set-mark " << ruleopt->getStr("tagvalue");
ostr << " --set-mark " << rule->getTagValue();
}
if (target=="CONNMARK")
{
ostr << ruleopt->getStr("CONNMARK_arg");
}
if (target=="CLASSIFY")
{
ostr << " --set-class " << ruleopt->getStr("classify_str");
}
if (target=="ROUTE")
{
string a;
a = ruleopt->getStr("ipt_iif");
if (!a.empty()) ostr << " --iif " << a;
a = ruleopt->getStr("ipt_oif");
if (!a.empty()) ostr << " --oif " << a;
a = ruleopt->getStr("ipt_gw");
if (!a.empty()) ostr << " --gw " << a;
bool c = ruleopt->getBool("ipt_continue");
if (c) ostr << " --continue";
c = ruleopt->getBool("ipt_tee");
if (c) ostr << " --tee";
}
return ostr.str();
}
string PolicyCompiler_ipt::PrintRule::_printMultiport(PolicyRule *rule)
{
RuleElementSrv *srvrel=rule->getSrv();
string s;
if(srvrel->size()>1 && rule->getBool("ipt_multiport"))
s= " -m multiport ";
return s;
}
string PolicyCompiler_ipt::PrintRule::_printDirectionAndInterface(PolicyRule *rule)
{
std::ostringstream ostr;
string iface_name = rule->getInterfaceStr();
if (iface_name.empty() || iface_name=="nil" ) return "";
RuleElementItf *itfrel = rule->getItf();
/* if interface name ends with '*', this is a wildcard
* interface. Iptables supports wildcard interfaces but uses '+' as a
* wildcard symbol */
string::size_type n;
if ( (n=iface_name.find("*"))!=string::npos) iface_name[n]='+';
Interface *rule_iface =
Interface::cast(compiler->dbcopy->findInIndex(rule->getInterfaceId()));
if (rule_iface && rule_iface->isBridgePort() &&
(version.empty() ||
XMLTools::version_compare(version, "1.3.0")>=0))
{
if (rule->getDirection()==PolicyRule::Inbound)
ostr << " -m physdev --physdev-in " << iface_name;
if (rule->getDirection()==PolicyRule::Outbound)
ostr << " -m physdev --physdev-out " << iface_name;
} else
{
if (rule->getDirection()==PolicyRule::Inbound)
ostr << _printSingleOptionWithNegation(" -i", itfrel, iface_name);
if (rule->getDirection()==PolicyRule::Outbound)
ostr << _printSingleOptionWithNegation(" -o", itfrel, iface_name);
}
// if (rule->getDirection()==PolicyRule::Both)
// compiler->output << "-i " << rule_iface->getName()
// << " -o " << rule_iface->getName();
ostr << " ";
return ostr.str();
}
string PolicyCompiler_ipt::PrintRule::_printActionOnReject(PolicyRule *rule)
{
std::ostringstream str;
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
// RuleElementSrv *srvrel=rule->getSrv();
Service *srv = compiler->getFirstSrv(rule);
assert(srv);
string s = ipt_comp->getActionOnReject(rule);
if (!s.empty())
{
if (ipt_comp->isActionOnRejectTCPRST(rule))
str << " --reject-with tcp-reset";
if (s.find("ICMP")!=string::npos)
{
if (ipt_comp->ipv6)
{
if (s.find("unreachable")!=string::npos)
{
if (s.find("net")!=string::npos ||
s.find("host")!=string::npos)
str << " --reject-with icmp6-addr-unreachable";
if (s.find("port")!=string::npos ||
s.find("proto")!=string::npos)
str << " --reject-with icmp6-port-unreachable";
}
if (s.find("prohibited")!=string::npos)
{
str << " --reject-with icmp6-adm-prohibited";
}
} else
{
if (s.find("unreachable")!=string::npos)
{
if (s.find("net")!=string::npos)
str << " --reject-with icmp-net-unreachable";
if (s.find("host")!=string::npos)
str << " --reject-with icmp-host-unreachable";
if (s.find("port")!=string::npos)
str << " --reject-with icmp-port-unreachable";
if (s.find("proto")!=string::npos)
str << " --reject-with icmp-proto-unreachable";
}
if (s.find("prohibited")!=string::npos)
{
if (s.find("net")!=string::npos)
str << " --reject-with icmp-net-prohibited";
if (s.find("host")!=string::npos)
str << " --reject-with icmp-host-prohibited";
if (XMLTools::version_compare(version, "1.2.9")>=0 &&
s.find("admin")!=string::npos)
str << " --reject-with icmp-admin-prohibited";
}
}
}
}
str << " ";
return str.str();
}
string PolicyCompiler_ipt::PrintRule::_printGlobalLogParameters()
{
return _printLogParameters(NULL);
}
string PolicyCompiler_ipt::PrintRule::_printLogPrefix(const string &rule_num,
const string &action,
const string &interf,
const string &chain,
const string &ruleset,
const string& ,
const string &prefix)
{
string s = prefix;
/* deal with our logging macros:
* %N - rule number ('2', or '2/3' for rule in a branch)
* %A - action
* %I - interface name
* %C - chain name
* %R - ruleset name
*/
string::size_type n;
if ((n=s.find("%N"))!=string::npos )
{
s.replace(n, 2, rule_num);
}
if ((n=s.find("%A"))!=string::npos )
{
s.replace(n, 2, action);
}
if ((n=s.find("%I"))!=string::npos )
{
s.replace(n, 2, interf);
}
if ((n=s.find("%C"))!=string::npos )
{
s.replace(n, 2, chain);
}
if ((n=s.find("%R"))!=string::npos )
{
s.replace(n, 2, ruleset);
}
if (s.length()>29)
{
compiler->warning(
"Log prefix has been truncated to 29 characters");
s=s.substr(0,29);
}
return _quote( s );
}
string PolicyCompiler_ipt::PrintRule::_printLogPrefix(PolicyRule *rule,
const string &prefix)
{
FWObject *ruleset = rule->getParent();
char action[64];
strncpy(action,rule->getStr("stored_action").c_str(),sizeof(action));
for (char *cptr=action; *cptr; cptr++) *cptr=toupper(*cptr);
string rule_iface = rule->getInterfaceStr();
if (rule_iface=="") rule_iface = "global";
std::ostringstream s1;
int pos=rule->getPosition();
// parent_rule_num is set by processor "Branching" for branch rules
string ppos = rule->getStr("parent_rule_num");
if (ppos != "")
s1 << ppos << "/";
s1 << pos;
return _printLogPrefix(s1.str(),
action,
rule_iface,
rule->getStr("ipt_chain"),
ruleset->getName(),
rule->getLabel(),
prefix);
}
string PolicyCompiler_ipt::PrintRule::_printLogParameters(PolicyRule *rule)
{
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
std::ostringstream str;
string s;
FWOptions *ruleopt = (rule!=NULL) ?
rule->getOptionsObject() : compiler->getCachedFwOpt();
// there is no ULOG for ip6tables yet
bool use_ulog = (!ipt_comp->ipv6 &&
compiler->getCachedFwOpt()->getBool("use_ULOG"));
if (use_ulog)
{
s=ruleopt->getStr("ulog_nlgroup");
if (s.empty()) s=compiler->getCachedFwOpt()->getStr("ulog_nlgroup");
if (!s.empty())
str << " --ulog-nlgroup " << s;
s=ruleopt->getStr("log_prefix");
if (s.empty()) s=compiler->getCachedFwOpt()->getStr("log_prefix");
if (!s.empty())
str << " --ulog-prefix " << _printLogPrefix(rule, s);
int r=compiler->getCachedFwOpt()->getInt("ulog_cprange");
if (r!=0) str << " --ulog-cprange " << r << " ";
r=compiler->getCachedFwOpt()->getInt("ulog_qthreshold");
if (r!=0) str << " --ulog-qthreshold " << r << " ";
} else
{
bool numeric_levels;
numeric_levels=compiler->getCachedFwOpt()->getBool("use_numeric_log_levels");
s=ruleopt->getStr("log_level");
if (s.empty()) s=compiler->getCachedFwOpt()->getStr("log_level");
if (!s.empty())
{
if ( numeric_levels )
{
if (s=="alert") s="1";
if (s=="crit") s="2";
if (s=="error") s="3";
if (s=="warning") s="4";
if (s=="notice") s="5";
if (s=="info") s="6";
if (s=="debug") s="7";
}
str << " --log-level " << s;
}
s=ruleopt->getStr("log_prefix");
if (s.empty()) s=compiler->getCachedFwOpt()->getStr("log_prefix");
if (!s.empty())
str << " --log-prefix " << _printLogPrefix(rule, s);
if (ruleopt->getBool("log_tcp_seq") || compiler->getCachedFwOpt()->getBool("log_tcp_seq"))
str << " --log-tcp-sequence ";
if (ruleopt->getBool("log_tcp_opt") || compiler->getCachedFwOpt()->getBool("log_tcp_opt"))
str << " --log-tcp-options ";
if (ruleopt->getBool("log_ip_opt") || compiler->getCachedFwOpt()->getBool("log_ip_opt"))
str << " --log-ip-options ";
}
return str.str();
}
string PolicyCompiler_ipt::PrintRule::_printLimit(libfwbuilder::PolicyRule *rule)
{
std::ostringstream str;
string s;
int l, lb;
FWOptions *ruleopt =rule->getOptionsObject();
FWOptions *compopt =compiler->getCachedFwOpt();
if ( (ruleopt!=NULL && (l=ruleopt->getInt("limit_value"))>0) ||
(l=compopt->getInt("limit_value"))>0 )
{
str << " -m limit --limit " << l;
if (ruleopt!=NULL) s=ruleopt->getStr("limit_suffix");
if (s.empty()) s=compopt->getStr("limit_suffix");
if (!s.empty()) str << s;
lb=-1;
if (ruleopt!=NULL) lb=ruleopt->getInt("limit_burst");
if (lb<0) lb=compopt->getInt("limit_burst");
if (lb>0) str << " --limit-burst " << lb;
}
return str.str();
}
string PolicyCompiler_ipt::PrintRule::_printProtocol(Service *srv)
{
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
string s;
// CustomService returns protocol name starting with v3.0.4
// However CustomService can return protocol name "any", which we should
// just skip.
if (CustomService::isA(srv))
{
// check if the code string for this custom service already includes
// "-p proto" fragment
string code = CustomService::cast(srv)->getCodeForPlatform(
compiler->myPlatformName());
std::size_t minus_p = code.find("-p ");
if (minus_p != string::npos) return "";
string pn = srv->getProtocolName();
if (pn == "any") return "";
}
if (!srv->isAny() && !TagService::isA(srv) && !UserService::isA(srv))
{
string pn = srv->getProtocolName();
if (pn=="ip" || pn=="any") pn = "all";
if (ipt_comp->ipv6)
{
if (ICMPService::isA(srv))
{
compiler->abort(
"Can not use ICMPService in ipv6 rule; "
"use ICMP6Service object instead");
}
if (ICMP6Service::isA(srv))
{
s = "-p ipv6-icmp ";
if (srv->getInt("type")!=-1 &&
(version.empty() ||
XMLTools::version_compare(version, "1.3.0")>=0))
s += " -m icmp6";
} else
{
// ip6tables issues warning for commands using "-p all"
// Warning: never matched protocol: all. use exension match instead
// Skip "-p all" if ipv6
if (pn!="all") s = "-p " + pn + " ";
}
} else
{
if (ICMP6Service::isA(srv))
{
compiler->abort(
"Can not use ICMP6Service in ipv4 rule; "
"use ICMPService object instead");
}
if (ICMPService::isA(srv))
{
s = "-p icmp ";
if (version.empty() ||
XMLTools::version_compare(version, "1.2.9")>=0)
s += " -m icmp ";
} else
{
s = "-p " + pn + " ";
}
}
if (pn == "tcp") s += "-m tcp ";
if (pn == "udp") s += "-m udp ";
}
return s;
}
string PolicyCompiler_ipt::PrintRule::_printPorts(int rs,int re)
{
std::ostringstream str;
compiler->normalizePortRange(rs,re);
if (rs>0 || re>0) {
if (rs==re) str << rs;
else
if (rs==0 && re!=0) str << ":" << re;
else
str << rs << ":" << re;
}
return str.str();
}
string PolicyCompiler_ipt::PrintRule::_printSrcPorts(Service *srv)
{
std::ostringstream str;
if (TCPService::isA(srv) || UDPService::isA(srv))
{
int rs = TCPUDPService::cast(srv)->getSrcRangeStart();
int re = TCPUDPService::cast(srv)->getSrcRangeEnd();
str << _printPorts(rs,re);
}
return str.str();
}
string PolicyCompiler_ipt::PrintRule::_printDstPorts(Service *srv)
{
std::ostringstream str;
if (TCPService::isA(srv) || UDPService::isA(srv))
{
int rs = TCPUDPService::cast(srv)->getDstRangeStart();
int re = TCPUDPService::cast(srv)->getDstRangeEnd();
str << _printPorts(rs,re);
}
return str.str();
}
string PolicyCompiler_ipt::PrintRule::_printICMP(ICMPService *srv)
{
std::ostringstream str;
if (ICMPService::cast(srv) && srv->getInt("type")!=-1)
{
str << srv->getStr("type");
if (srv->getInt("code")!=-1)
str << "/" << srv->getStr("code") << " ";
}
return str.str();
}
string PolicyCompiler_ipt::PrintRule::_printIP(IPService *srv, PolicyRule *rule)
{
PolicyCompiler_ipt *ipt_comp=dynamic_cast<PolicyCompiler_ipt*>(compiler);
std::ostringstream str;
if (srv->getBool("fragm") || srv->getBool("short_fragm"))
{
if (ipt_comp->ipv6) str << " -m frag --fragmore";
else str << " -f ";
}
string tos = srv->getTOSCode();
string dscp = srv->getDSCPCode();
if (!tos.empty())
str << " -m tos --tos " << tos;
else
if (!dscp.empty())
{
if (dscp.find("BE")==0 ||
dscp.find("EF")==0 ||
dscp.find("AF")==0 ||
dscp.find("CS")==0)
str << " -m dscp --dscp-class " << dscp;
else
str << " -m dscp --dscp " << dscp;
}
if (srv->hasIpOptions())
{
if (!ipt_comp->ipv6)
{
str << " -m ipv4options ";
if (srv->getBool("any_opt")) str << " --any-opt";
else
{
if (srv->getBool("lsrr")) str << " --lsrr";
if (srv->getBool("ssrr")) str << " --ssrr";
if (srv->getBool("rr")) str << " --rr";
if (srv->getBool("ts")) str << " --ts";
if (srv->getBool("rtralt")) str << " --ra";
}
} else
{
compiler->abort(
rule,
"IP options match is not supported for IPv6.");
}
}
return str.str();
}
string PolicyCompiler_ipt::PrintRule::_printTCPFlags(libfwbuilder::TCPService *srv)
{
string str;
if (srv->inspectFlags())
{
TCPService::TCPFlag f1[2]={ TCPService::SYN };
TCPService::TCPFlag f2[7]={ TCPService::URG,
TCPService::ACK,
TCPService::PSH,
TCPService::RST,
TCPService::SYN,
TCPService::FIN };
std::set<TCPService::TCPFlag> none;
std::set<TCPService::TCPFlag> syn( f1, f1+1 );
std::set<TCPService::TCPFlag> all_masks( f2 , f2+6 );
if (srv->getAllTCPFlags()==syn && srv->getAllTCPFlagMasks()==all_masks)
str=" --tcp-flags SYN,RST,ACK SYN ";
else
{
str=" --tcp-flags ";
bool first=true;
if (srv->getAllTCPFlagMasks()==all_masks) str+="ALL";
else
{
if (srv->getTCPFlagMask(TCPService::URG)) { if (!first) str+=","; str+="URG"; first=false; }
if (srv->getTCPFlagMask(TCPService::ACK)) { if (!first) str+=","; str+="ACK"; first=false; }
if (srv->getTCPFlagMask(TCPService::PSH)) { if (!first) str+=","; str+="PSH"; first=false; }
if (srv->getTCPFlagMask(TCPService::RST)) { if (!first) str+=","; str+="RST"; first=false; }
if (srv->getTCPFlagMask(TCPService::SYN)) { if (!first) str+=","; str+="SYN"; first=false; }
if (srv->getTCPFlagMask(TCPService::FIN)) { if (!first) str+=","; str+="FIN"; first=false; }
}
str+=" ";
if (srv->getAllTCPFlags()==none) str+="NONE";
else
{
first=true;
if (srv->getTCPFlag(TCPService::URG)) { if (!first) str+=","; str+="URG"; first=false; }
if (srv->getTCPFlag(TCPService::ACK)) { if (!first) str+=","; str+="ACK"; first=false; }
if (srv->getTCPFlag(TCPService::PSH)) { if (!first) str+=","; str+="PSH"; first=false; }
if (srv->getTCPFlag(TCPService::RST)) { if (!first) str+=","; str+="RST"; first=false; }
if (srv->getTCPFlag(TCPService::SYN)) { if (!first) str+=","; str+="SYN"; first=false; }
if (srv->getTCPFlag(TCPService::FIN)) { if (!first) str+=","; str+="FIN"; first=false; }
}
}
}
return str;
}
/*
* we made sure that all services in rel represent the same protocol
*/
string PolicyCompiler_ipt::PrintRule::_printSrcService(RuleElementSrv *rel)
{
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
std::ostringstream ostr;
/* I do not want to use rel->getFirst because it traverses the tree to
* find the object. I'd rather use a cached copy in the compiler
*/
FWObject *o=rel->front();
if (o && FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
Service *srv= Service::cast(o);
if (rel->size()==1)
{
if (UDPService::isA(srv) || TCPService::isA(srv) ||
TagService::isA(srv))
{
string str=_printSrcPorts( srv );
if (! str.empty() )
{
ostr << _printSingleOptionWithNegation(" --sport", rel, str);
}
}
} else
{
/* use multiport */
string str;
bool first=true;
for (FWObject::iterator i=rel->begin(); i!=rel->end(); i++)
{
FWObject *o= *i;
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
Service *s=Service::cast( o );
assert(s);
if (UDPService::isA(srv) || TCPService::isA(srv))
{
if (!first) str+=",";
str+= _printSrcPorts( s );
if (!str.empty()) first=false;
}
}
if ( !str.empty() )
{
if (ipt_comp->newIptables(version))
ostr << " --sports ";
else
ostr << " --source-port ";
ostr << str << " ";
}
}
return ostr.str();
}
string PolicyCompiler_ipt::PrintRule::_printDstService(RuleElementSrv *rel)
{
PolicyCompiler_ipt *ipt_comp=dynamic_cast<PolicyCompiler_ipt*>(compiler);
std::ostringstream ostr;
FWObject *o=rel->front();
if (o && FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
Service *srv= Service::cast(o);
if (rel->size()==1)
{
if (UDPService::isA(srv) || TCPService::isA(srv))
{
string str=_printDstPorts( srv );
if (! str.empty() )
{
ostr << _printSingleOptionWithNegation(" --dport", rel, str);
}
}
if (TCPService::isA(srv))
{
string str=_printTCPFlags(TCPService::cast(srv));
if (!str.empty())
{
ostr << _printSingleOptionWithNegation("", rel, str);
}
}
if (ICMPService::isA(srv) || ICMP6Service::isA(srv))
{
string icmp_type_str =
(ipt_comp->ipv6) ? " --icmpv6-type" : " --icmp-type";
string str = _printICMP( ICMPService::cast(srv) );
if (str.empty() )
{
// module icmp6 does not like "--icmp6-type any"
if ((version.empty() ||
XMLTools::version_compare(version, "1.2.6")>0) &&
!ipt_comp->ipv6)
ostr << icmp_type_str << " any ";
} else
{
ostr << _printSingleOptionWithNegation(icmp_type_str, rel, str);
}
}
if (IPService::isA(srv))
{
string str = _printIP(IPService::cast(srv), PolicyRule::cast(rel->getParent()));
if (! str.empty() )
{
ostr << _printSingleObjectNegation(rel) << str << " ";
}
}
if (CustomService::isA(srv))
{
ostr << _printSingleObjectNegation(rel) << " "
<< CustomService::cast(srv)->getCodeForPlatform( compiler->myPlatformName() ) << " ";
}
if (TagService::isA(srv))
{
ostr << "-m mark "
<< _printSingleObjectNegation(rel)
<< "--mark "
<< TagService::constcast(srv)->getCode() << " ";
}
if (UserService::isA(srv))
{
ostr << "-m owner "
<< _printSingleObjectNegation(rel)
<< "--uid-owner "
<< UserService::cast(srv)->getUserId() << " ";
}
} else
{
/* use multiport */
string str;
for (FWObject::iterator i=rel->begin(); i!=rel->end(); i++)
{
FWObject *o= *i;
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
Service *s=Service::cast( o );
assert(s);
if (UDPService::isA(srv) || TCPService::isA(srv))
{
string str1 = _printDstPorts( s );
if (str!="" && str1!="") str+=",";
str+=str1;
}
}
if ( !str.empty() )
{
if (ipt_comp->newIptables(version))
ostr << " --dports ";
else
ostr << " --destination-port ";
ostr << str << " ";
}
}
return ostr.str();
}
string PolicyCompiler_ipt::PrintRule::_printSrcAddr(RuleElement *rel, Address *o)
{
string res;
if (AddressRange::cast(o)!=NULL)
{
AddressRange *ar = AddressRange::cast(o);
const InetAddr &range_start = ar->getRangeStart();
const InetAddr &range_end = ar->getRangeEnd();
if (range_start != range_end)
{
if (!have_m_iprange) { res = "-m iprange "; have_m_iprange = true; }
res += _printSingleObjectNegation(rel) + "--src-range ";
res += range_start.toString() + "-" + range_end.toString() + " ";
} else
res += "-s " + range_start.toString() + " ";
return res;
}
return _printSingleOptionWithNegation(" -s", rel, _printAddr(o));
}
string PolicyCompiler_ipt::PrintRule::_printDstAddr(RuleElement *rel, Address *o)
{
string res;
if (AddressRange::cast(o)!=NULL)
{
AddressRange *ar = AddressRange::cast(o);
const InetAddr &range_start = ar->getRangeStart();
const InetAddr &range_end = ar->getRangeEnd();
if (range_start != range_end)
{
if (!have_m_iprange) { res = "-m iprange "; have_m_iprange = true; }
res += _printSingleObjectNegation(rel) + "--dst-range ";
res += range_start.toString() + "-" + range_end.toString() + " ";
} else
res += "-d " + range_start.toString() + " ";
return res;
}
return _printSingleOptionWithNegation(" -d", rel, _printAddr(o));
}
string PolicyCompiler_ipt::PrintRule::_printAddr(Address *o)
{
PolicyCompiler_ipt *ipt_comp=dynamic_cast<PolicyCompiler_ipt*>(compiler);
std::ostringstream ostr;
MultiAddressRunTime *atrt = MultiAddressRunTime::cast(o);
if (atrt!=NULL)
{
if (atrt->getSubstitutionTypeName()==AddressTable::TYPENAME)
{
ostr << "$" << ipt_comp->getAddressTableVarName(atrt) << " ";
return ostr.str();
}
if (atrt->getSubstitutionTypeName()==DNSName::TYPENAME)
{
return atrt->getSourceName();
}
// at this time we only support two types of MultiAddress
// objects: AddressTable and DNSName. Both should be converted
// to MultiAddressRunTime at this point. If we get some other
// kind of MultiAddressRunTime object, we do not know what to do
// with it so we stop.
assert(atrt==NULL);
}
if (Interface::cast(o)!=NULL)
{
Interface *iface=Interface::cast(o);
if (iface->isDyn())
ostr << "$" << ipt_comp->getInterfaceVarName(iface, ipt_comp->ipv6)
<< " ";
return ostr.str();
}
const InetAddr *addr = o->getAddressPtr();
const InetAddr *mask = o->getNetmaskPtr();
if (addr==NULL)
{
compiler->warning(
string("Empty inet address in object ") +
o->getName() + "(" +
FWObjectDatabase::getStringId(o->getId())
+ ")");
return ostr.str();
}
// Note that mask can be NULL, for example if o is AddressRange.
if (addr->isAny() && (mask==NULL || mask->isAny()))
{
ostr << "0/0 ";
} else
{
ostr << addr->toString();
if (Interface::cast(o)==NULL &&
Address::cast(o)->dimension() > 1 &&
!mask->isHostMask())
{
ostr << "/" << mask->getLength();
}
ostr << " ";
}
return ostr.str();
}
string PolicyCompiler_ipt::PrintRule::_printSingleObjectNegation(
RuleElement *rel)
{
if (rel->getBool("single_object_negation")) return "! ";
else return "";
}
string PolicyCompiler_ipt::PrintRule::_printTimeInterval(PolicyRule *r)
{
std::ostringstream ostr;
RuleElementInterval* ri=r->getWhen();
if (ri==NULL || ri->isAny()) return "";
std::map<int,std::string> daysofweek;
daysofweek[0]="Sun";
daysofweek[1]="Mon";
daysofweek[2]="Tue";
daysofweek[3]="Wed";
daysofweek[4]="Thu";
daysofweek[5]="Fri";
daysofweek[6]="Sat";
daysofweek[7]="Sun";
int smin, shour, sday, smonth, syear, sdayofweek;
int emin, ehour, eday, emonth, eyear, edayofweek;
string days_of_week;
Interval *interval = compiler->getFirstWhen(r);
assert(interval!=NULL);
interval->getStartTime( &smin, &shour, &sday, &smonth, &syear, &sdayofweek);
interval->getEndTime( &emin, &ehour, &eday, &emonth, &eyear, &edayofweek);
days_of_week = interval->getDaysOfWeek();
if (shour<0) shour=0;
if (smin<0) smin=0;
if (ehour<0) ehour=23;
if (emin<0) emin=59;
ostr << "-m time ";
bool use_timestart_timestop = true;
if (XMLTools::version_compare(version, "1.4.0")>=0)
{
// in 1.4.0 date format has changed, it is now ISO 8601
// http://www.w3.org/TR/NOTE-datetime
if (sday>0 && smonth>0 && syear>0)
{
ostr << "--datestart "
<< setw(2) << setfill('0') << syear << "-"
<< setw(2) << setfill('0') << smonth << "-"
<< setw(2) << setfill('0') << sday << "T"
<< setw(2) << setfill('0') << shour << ":"
<< setw(2) << setfill('0') << smin << ":00Z ";
use_timestart_timestop = false;
}
if (eday>0 && emonth>0 && eyear>0)
{
ostr << "--datestop "
<< setw(2) << setfill('0') << eyear << "-"
<< setw(2) << setfill('0') << emonth << "-"
<< setw(2) << setfill('0') << eday << "T"
<< setw(2) << setfill('0') << ehour << ":"
<< setw(2) << setfill('0') << emin << ":00Z ";
use_timestart_timestop = false;
}
if (use_timestart_timestop)
{
ostr << " --timestart "
<< setw(2) << setfill('0') << shour << ":"
<< setw(2) << setfill('0') << smin << " ";
ostr << " --timestop "
<< setw(2) << setfill('0') << ehour << ":"
<< setw(2) << setfill('0') << emin << " ";
}
if (!days_of_week.empty() && days_of_week != "0,1,2,3,4,5,6")
{
ostr << " --weekdays ";
istringstream istr(days_of_week);
bool first= true;
while (!istr.eof())
{
if (!first) ostr << ',';
first = false;
int d;
istr >> d;
ostr << daysofweek[d];
char sep;
istr >> sep;
}
}
} else
{
/* "old" iptables time module
TIME v1.2.11 options:
--timestart value --timestop value --days listofdays
timestart value : HH:MM
timestop value : HH:MM
listofdays value: a list of days to apply -> ie. Mon,Tue,Wed,Thu,Fri.
Case sensitive
*/
ostr << " --timestart "
<< setw(2) << setfill('0') << shour << ":"
<< setw(2) << setfill('0') << smin << " ";
ostr << " --timestop "
<< setw(2) << setfill('0') << ehour << ":"
<< setw(2) << setfill('0') << emin << " ";
if (!days_of_week.empty() && days_of_week != "0,1,2,3,4,5,6")
{
ostr << " --days ";
istringstream istr(days_of_week);
bool first= true;
while (!istr.eof())
{
if (!first) ostr << ',';
first = false;
int d;
istr >> d;
ostr << daysofweek[d];
char sep;
istr >> sep;
}
}
}
return ostr.str();
}
PolicyCompiler_ipt::PrintRule::PrintRule(const std::string &name) :
PolicyRuleProcessor(name)
{
init = true;
print_once_on_top = true;
// use delayed initialization for ipt_comp->minus_n_commands
// because it requires pointer to the compiler which has not been
// initialized yet when this constructor is executed.
minus_n_tracker_initialized = false;
}
/*
* Initialize some internal variables. Need to do this in a separate
* method because pointer to the compiler object is set by
* RuleProcessor::setContext and is not available in constructor.
*/
void PolicyCompiler_ipt::PrintRule::initialize()
{
// retrieve and save version for _printSingleOptionWithNegation and others
version = compiler->fw->getStr("version");
}
bool PolicyCompiler_ipt::PrintRule::processNext()
{
PolicyCompiler_ipt *ipt_comp=dynamic_cast<PolicyCompiler_ipt*>(compiler);
PolicyRule *rule =getNext();
if (rule==NULL) return false;
string chain = rule->getStr("ipt_chain");
if (ipt_comp->chain_usage_counter[chain] > 0)
{
tmp_queue.push_back(rule);
compiler->output << _printRuleLabel(rule);
compiler->output << _createChain(rule->getStr("ipt_chain"));
compiler->output << _createChain(rule->getStr("ipt_target"));
compiler->output
<< dynamic_cast<OSConfigurator_linux24*>(compiler->osconfigurator)->
printRunTimeWrappers(rule, PolicyRuleToString(rule), ipt_comp->ipv6);
}
return true;
}
string PolicyCompiler_ipt::PrintRule::PolicyRuleToString(PolicyRule *rule)
{
FWOptions *ruleopt = rule->getOptionsObject();
FWObject *ref;
RuleElementSrc *srcrel=rule->getSrc();
ref=srcrel->front();
Address *src=Address::cast(FWReference::cast(ref)->getPointer());
if(src==NULL)
compiler->abort(rule, string("Broken SRC in ") + rule->getLabel());
RuleElementDst *dstrel=rule->getDst();
ref=dstrel->front();
Address *dst=Address::cast(FWReference::cast(ref)->getPointer());
if(dst==NULL)
compiler->abort(rule, string("Broken DST in ") + rule->getLabel());
RuleElementSrv *srvrel=rule->getSrv();
ref=srvrel->front();
Service *srv=Service::cast(FWReference::cast(ref)->getPointer());
if(srv==NULL)
compiler->abort(rule, string("Broken SRV in ") + rule->getLabel());
std::ostringstream command_line;
have_m_iprange = false;
command_line << _startRuleLine();
command_line << _printChain(rule);
command_line << _printDirectionAndInterface(rule);
command_line << _printProtocol(srv);
command_line << _printMultiport(rule);
if (!src->isAny())
{
if (physAddress::isA(src) || combinedAddress::isA(src))
{
string physaddress = "";
if (physAddress::isA(src))
{
physaddress = physAddress::cast(src)->getPhysAddress();
if (physaddress.empty())
{
compiler->warning(
rule,
"Empty MAC address in rule");
physaddress = "00:00:00:00:00:00";
}
}
if (combinedAddress::isA(src))
physaddress = combinedAddress::cast(src)->getPhysAddress();
/* physAddress component of combinedAddress can be empty. For example
* this happens when an object with both IP and MAC addresses is found
* in "source" and rule is determined to go into OUTPUT chain. On the
* other hand, if physAddress object has no MAC address, it is always
* an error.
*/
if (!physaddress.empty())
{
command_line << " -m mac";
command_line << _printSingleOptionWithNegation(" --mac-source",
srcrel,
physaddress);
}
/*
* fool-proof: this is last resort check for situation when user
* created IPv4 object for the interface but left it with empty
* address ( 0.0.0.0 ).
*
* note that combinedAddress inherits IPv4 and therefore
* combinedAddress::hasInetAddress returns true;
*
*/
if (src->hasInetAddress() && !src->getAddressPtr()->isAny())
command_line << _printSrcAddr(srcrel, src);
} else
command_line << _printSrcAddr(srcrel, src);
}
command_line << _printSrcService(srvrel);
if (!dst->isAny())
command_line << _printDstAddr(dstrel, dst);
command_line << _printDstService(srvrel);
/* keeping state does not apply to deny/reject
however some rules need state check even if action is Deny
autoupgrade transformation 2.1.11 -> 2.1.12 adds rule option
'stateless=True' for rules with action NOT 'Accept', 'Tag' or
'Route'. No need to check action here, just rely on this option
and internal flag 'force_state_check' (05/07/07 --vk)
*/
if (!ruleopt->getBool("stateless") || rule->getBool("force_state_check") )
{
/*
* But not, when the line already contains a state matching
*/
if (command_line.str().find("-m state --state", 0) == string::npos)
command_line << " -m state --state NEW ";
}
command_line << _printTimeInterval(rule);
command_line << _printModules(rule);
command_line << _printTarget(rule);
command_line << _endRuleLine();
// command_line << endl;
return command_line.str();
}
string PolicyCompiler_ipt::PrintRule::_declareTable()
{
return "";
}
string PolicyCompiler_ipt::PrintRule::_commit()
{
return "";
}
string PolicyCompiler_ipt::PrintRule::_clampTcpToMssRule()
{
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
ostringstream res;
if ( compiler->getCachedFwOpt()->getBool("clamp_mss_to_mtu"))
{
bool ipforw;
if (ipt_comp->ipv6)
{
string s = compiler->getCachedFwOpt()->getStr("linux24_ipv6_forward");
ipforw = (s.empty() || s=="1" || s=="On" || s=="on");
// bug #2477775: target TCPMSS is not available in ip6tables
// before 1.4.0 In fact I am not sure of the minimal required
// version. According to the netfilter git log, it was added in
// 1.3.8
if (XMLTools::version_compare(version, "1.3.8")<0)
{
if (ipforw)
{
res << "target TCPMSS is not supported by ip6tables before v1.3.8";
compiler->warning(res.str());
return "# " + res.str() + "\n\n";
} else return "";
}
} else
{
string s = compiler->getCachedFwOpt()->getStr("linux24_ip_forward");
ipforw = (s.empty() || s=="1" || s=="On" || s=="on");
}
if (ipforw)
{
res << _startRuleLine()
<< "FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu"
<< _endRuleLine();
res << endl;
}
}
return res.str();
}
string PolicyCompiler_ipt::PrintRule::_printOptionalGlobalRules()
{
PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);
ostringstream res;
bool isIPv6 = ipt_comp->ipv6;
string s = compiler->getCachedFwOpt()->getStr("linux24_ip_forward");
bool ipforward= (s.empty() || s=="1" || s=="On" || s=="on");
s = compiler->getCachedFwOpt()->getStr("linux24_ipv6_forward");
bool ip6forward= (s.empty() || s=="1" || s=="On" || s=="on");
bool ipforw = ((!ipt_comp->ipv6 && ipforward) ||
(ipt_comp->ipv6 && ip6forward));
Configlet configlet(compiler->fw, "linux24", "automatic_rules");
configlet.removeComments();
configlet.collapseEmptyStrings(true);
configlet.setVariable("begin_rule", _startRuleLine().c_str());
configlet.setVariable("end_rule", _endRuleLine().c_str());
configlet.setVariable("ipforw", ipforw);
configlet.setVariable("accept_established",
compiler->getCachedFwOpt()->getBool("accept_established") &&
ipt_comp->my_table=="filter");
if ( compiler->getCachedFwOpt()->getBool("mgmt_ssh") &&
! compiler->getCachedFwOpt()->getStr("mgmt_addr").empty() )
{
string addr_str = compiler->getCachedFwOpt()->getStr("mgmt_addr");
InetAddrMask *inet_addr = NULL;
bool addr_is_good = true;
if (isIPv6)
{
// check if given address is ipv6
try
{
inet_addr = new Inet6AddrMask(addr_str);
} catch(const FWException &ex) {
// address does not parse as ipv6, skip this rule.
addr_is_good = false;
}
} else
{
// check if given address parses as ipv4
try
{
inet_addr = new InetAddrMask(addr_str);
} catch(const FWException &ex) {
// address does not parse
addr_is_good = false;
}
}
if (addr_is_good)
{
configlet.setVariable("mgmt_access", 1);
configlet.setVariable("management_address", inet_addr->toString().c_str());
} else
{
QString err("Backup ssh access rule could not be added "
"because specified address '%1' is invalid");
compiler->warning(err.arg(addr_str.c_str()).toStdString());
}
}
configlet.setVariable(
"drop_new_tcp_with_no_syn",
! compiler->getCachedFwOpt()->getBool("accept_new_tcp_with_no_syn"));
configlet.setVariable(
"add_rules_for_ipv6_neighbor_discovery",
isIPv6 &&
compiler->getCachedFwOpt()->getBool("add_rules_for_ipv6_neighbor_discovery"));
configlet.setVariable("drop_invalid",
compiler->getCachedFwOpt()->getBool("drop_invalid") &&
!compiler->getCachedFwOpt()->getBool("log_invalid"));
configlet.setVariable("drop_invalid_and_log",
compiler->getCachedFwOpt()->getBool("drop_invalid") &&
compiler->getCachedFwOpt()->getBool("log_invalid"));
configlet.setVariable("create_drop_invalid_chain",
_createChain("drop_invalid").c_str());
if (compiler->getCachedFwOpt()->getBool("log_invalid") &&
!isIPv6 &&
compiler->getCachedFwOpt()->getBool("use_ULOG"))
{
configlet.setVariable("use_ulog", 1);
string s = compiler->getCachedFwOpt()->getStr("ulog_nlgroup");
configlet.setVariable("use_nlgroup", !s.empty());
configlet.setVariable("nlgroup", s.c_str());
int r = compiler->getCachedFwOpt()->getInt("ulog_cprange");
configlet.setVariable("use_cprange", r!=0);
configlet.setVariable("cprange", r);
r = compiler->getCachedFwOpt()->getInt("ulog_qthreshold");
configlet.setVariable("use_qthreshold", r!=0);
configlet.setVariable("qthreshold", r);
} else
configlet.setVariable("not_use_ulog", 1);
configlet.setVariable("invalid_match_log_prefix",
_printLogPrefix("-1",
"DENY",
"global",
"drop_invalid",
"Policy",
"BLOCK INVALID",
"INVALID state -- DENY ").c_str());
return configlet.expand().toStdString();
}
string PolicyCompiler_ipt::PrintRule::_quote(const string &s)
{
return "\"" + s + "\"";
}