mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-03-19 17:57:22 +01:00
fixes #651 Shell functions that read ip addresses of interfaces moved to configlet run_time_wrappers; using shell loops in generated script since now we read all ipv4 and ipv6 addresses of dynamic interfaces
This commit is contained in:
parent
758ce50c13
commit
488a50251e
@ -59,6 +59,10 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include <QString>
|
||||
#include <QtDebug>
|
||||
#include <QregExp>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
using namespace libfwbuilder;
|
||||
using namespace fwcompiler;
|
||||
@ -71,6 +75,12 @@ OSConfigurator_linux24::OSConfigurator_linux24(FWObjectDatabase *_db,
|
||||
bool ipv6_policy) :
|
||||
OSConfigurator(_db, fw, ipv6_policy) , os_data(fw->getStr("host_OS"))
|
||||
{
|
||||
command_wrappers = new Configlet(fw, "linux24", "run_time_wrappers");
|
||||
}
|
||||
|
||||
OSConfigurator_linux24::~OSConfigurator_linux24()
|
||||
{
|
||||
delete command_wrappers;
|
||||
}
|
||||
|
||||
string OSConfigurator_linux24::getInterfaceVarName(FWObject *iface, bool v6)
|
||||
@ -406,10 +416,119 @@ string OSConfigurator_linux24::generateCodeForProtocolHandlers()
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
string OSConfigurator_linux24::printRunTimeWrappers(FWObject *rule,
|
||||
const string &command,
|
||||
bool ipv6)
|
||||
QString OSConfigurator_linux24::addressTableWrapper(FWObject *rule,
|
||||
const QString &command,
|
||||
bool ipv6)
|
||||
{
|
||||
QString combined_command = command;
|
||||
QRegExp address_table_re("\\$at_(\\S+)");
|
||||
int pos = address_table_re.indexIn(command);
|
||||
if (pos > -1)
|
||||
{
|
||||
QStringList command_lines = QString(command).split("\n", QString::SkipEmptyParts);
|
||||
if (command_lines.size() > 1)
|
||||
{
|
||||
command_lines.push_front("{");
|
||||
command_lines.push_back("}");
|
||||
}
|
||||
combined_command = command_lines.join("\n");
|
||||
|
||||
command_wrappers->clear();
|
||||
command_wrappers->removeComments();
|
||||
command_wrappers->collapseEmptyStrings(true);
|
||||
command_wrappers->setVariable("ipv6", ipv6);
|
||||
|
||||
QString at_var = address_table_re.cap(1);
|
||||
QString at_file = rule->getStr("address_table_file").c_str();
|
||||
|
||||
command_wrappers->setVariable("address_table_file", at_file);
|
||||
command_wrappers->setVariable("address_table_var", at_var);
|
||||
command_wrappers->setVariable("command", combined_command);
|
||||
command_wrappers->setVariable("address_table", true);
|
||||
command_wrappers->setVariable("wildcard_interface", false);
|
||||
command_wrappers->setVariable("no_dyn_addr", false);
|
||||
command_wrappers->setVariable("one_dyn_addr", false);
|
||||
command_wrappers->setVariable("two_dyn_addr", false);
|
||||
|
||||
combined_command = command_wrappers->expand();
|
||||
}
|
||||
return combined_command;
|
||||
}
|
||||
|
||||
string OSConfigurator_linux24::printRunTimeWrappers(FWObject *rule,
|
||||
const string &command,
|
||||
bool ipv6)
|
||||
{
|
||||
/* if anywhere in command_line we used variable holding an address of
|
||||
* dynamic interface (named $i_something) then we need to add this
|
||||
* command with a check for the value of this variable. We execute
|
||||
* iptables command only if the value is a non-empty string.
|
||||
*
|
||||
* bug #1851166: there could be two dynamic interfaces in the same
|
||||
* rule.
|
||||
*/
|
||||
|
||||
bool wildcard_interface = false;
|
||||
QString combined_command = addressTableWrapper(rule, command.c_str(), ipv6);
|
||||
|
||||
command_wrappers->clear();
|
||||
command_wrappers->removeComments();
|
||||
command_wrappers->collapseEmptyStrings(true);
|
||||
command_wrappers->setVariable("ipv6", ipv6);
|
||||
|
||||
command_wrappers->setVariable("address_table", false);
|
||||
|
||||
QRegExp intf_re("\\$i_(\\S+)");
|
||||
|
||||
QStringList iface_names;
|
||||
QStringList iface_vars;
|
||||
int pos = -1;
|
||||
while ((pos = intf_re.indexIn(combined_command, pos + 1)) > -1)
|
||||
{
|
||||
QString name = intf_re.cap(1);
|
||||
iface_names.push_back(name);
|
||||
iface_vars.push_back("$i_" + name);
|
||||
if (name.contains("*"))
|
||||
{
|
||||
wildcard_interface = true;
|
||||
QString intf_family = name.section('*', 0);
|
||||
command_wrappers->setVariable("interface_family_name", intf_family);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool no_wrapper = !wildcard_interface && iface_names.size() == 0;
|
||||
|
||||
if (!no_wrapper)
|
||||
{
|
||||
QStringList command_lines = QString(combined_command).split("\n", QString::SkipEmptyParts);
|
||||
if (command_lines.size() > 1)
|
||||
{
|
||||
command_lines.push_front("{");
|
||||
command_lines.push_back("}");
|
||||
}
|
||||
combined_command = command_lines.join("\n");
|
||||
}
|
||||
|
||||
command_wrappers->setVariable("no_wrapper", no_wrapper);
|
||||
command_wrappers->setVariable("wildcard_interface", wildcard_interface);
|
||||
command_wrappers->setVariable("one_dyn_addr",
|
||||
!wildcard_interface && iface_names.size() == 1);
|
||||
command_wrappers->setVariable("two_dyn_addr",
|
||||
!wildcard_interface && iface_names.size() > 1);
|
||||
|
||||
for (int idx=0; idx<iface_names.size(); ++idx)
|
||||
{
|
||||
QString intf_name = iface_names[idx];
|
||||
if (ipv6) intf_name += "_v6";
|
||||
command_wrappers->setVariable(QString("intf_%1_var_name").arg(idx+1), intf_name);
|
||||
}
|
||||
|
||||
command_wrappers->setVariable("command", combined_command);
|
||||
|
||||
return command_wrappers->expand().toStdString() + "\n";
|
||||
|
||||
#if 0
|
||||
string command_line = command;
|
||||
ostringstream ext_command_line;
|
||||
|
||||
@ -442,16 +561,6 @@ string OSConfigurator_linux24::printRunTimeWrappers(FWObject *rule,
|
||||
if (p1==string::npos) break;
|
||||
}
|
||||
|
||||
/* if anywhere in command_line we used variable holding an address of
|
||||
* dynamic interface (named $i_something) then we need to add this
|
||||
* command with a check for the value of this variable. We execute
|
||||
* iptables command only if the value is a non-empty string.
|
||||
*
|
||||
* bug #1851166: there could be two dynamic interfaces in the same
|
||||
* rule.
|
||||
*/
|
||||
if (command_line.find("$i_")==string::npos) return command_line;
|
||||
|
||||
string getaddr_function_name = "getaddr";
|
||||
if (ipv6) getaddr_function_name = "getaddr6";
|
||||
|
||||
@ -508,6 +617,8 @@ string OSConfigurator_linux24::printRunTimeWrappers(FWObject *rule,
|
||||
}
|
||||
|
||||
return res.str();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
string OSConfigurator_linux24::printIPForwardingCommands()
|
||||
|
||||
@ -32,6 +32,8 @@
|
||||
|
||||
#include "OSData.h"
|
||||
|
||||
class QString;
|
||||
|
||||
namespace libfwbuilder {
|
||||
class FWObject;
|
||||
class MultiAddressRunTime;
|
||||
@ -44,7 +46,8 @@ namespace fwcompiler {
|
||||
class OSConfigurator_linux24 : public OSConfigurator {
|
||||
|
||||
OSData os_data;
|
||||
|
||||
Configlet *command_wrappers;
|
||||
|
||||
std::map<std::string,std::string> address_table_objects;
|
||||
|
||||
// this vector is used to avoid duplication of virtual addresses for nat
|
||||
@ -62,10 +65,13 @@ namespace fwcompiler {
|
||||
void setConfigletMacroForOptionInt(int opt,
|
||||
Configlet *c,
|
||||
const char *option_name);
|
||||
virtual QString addressTableWrapper(libfwbuilder::FWObject *rule,
|
||||
const QString &command,
|
||||
bool ipv6=false);
|
||||
|
||||
public:
|
||||
|
||||
virtual ~OSConfigurator_linux24() {};
|
||||
virtual ~OSConfigurator_linux24();
|
||||
OSConfigurator_linux24(libfwbuilder::FWObjectDatabase *_db,
|
||||
libfwbuilder::Firewall *fw, bool ipv6_policy);
|
||||
|
||||
|
||||
55
src/res/configlets/linux24/run_time_wrappers
Normal file
55
src/res/configlets/linux24/run_time_wrappers
Normal file
@ -0,0 +1,55 @@
|
||||
## -*- mode: shell-script; -*-
|
||||
|
||||
{{if no_wrapper}}
|
||||
{{$command}}
|
||||
{{endif}}
|
||||
|
||||
|
||||
{{if address_table}}
|
||||
grep -Ev '^#|^;|^\s*$' {{$address_table_file}} | while read L ; do
|
||||
set $L; at_{{$address_table_var}}=$1; {{$command}}
|
||||
done
|
||||
{{endif}}
|
||||
|
||||
##
|
||||
## Current implementation supports only one wildcard interface per rule.
|
||||
## This can be something like "ppp*"
|
||||
##
|
||||
{{if whildcard_interface}}
|
||||
getinterfaces {{$interface_family_name}} | while read I; do
|
||||
ivar=$(getInterfaceVarName $I)
|
||||
getaddr{{if ipv6}}6{{endif}} $I $ivar
|
||||
cmd="$"$ivar
|
||||
eval "addr=$cmd"
|
||||
test -n "$addr" && {{$command}}
|
||||
{{endif}}
|
||||
|
||||
## If the rule uses address of dynamic interface, there can be either
|
||||
## one such address or two (source and destination). It impossible to
|
||||
## have more than two.
|
||||
|
||||
##
|
||||
## intf_name is the name of the interface plus "_v6" suffix if ipv6
|
||||
## such as "ppp0" or "ppp0_v6"
|
||||
## This is so because we call getaddr6 function with variable name
|
||||
## constructed with suffix _v6
|
||||
##
|
||||
{{if one_dyn_addr}}
|
||||
for i_{{$intf_1_var_name}} in $i_{{$intf_1_var_name}}_list
|
||||
do
|
||||
test -n "$i_{{$intf_1_var_name}}" && {{$command}}
|
||||
done
|
||||
{{endif}}
|
||||
|
||||
|
||||
{{if two_dyn_addr}}
|
||||
for i_{{$intf_1_var_name}} in $i_{{$intf_1_var_name}}_list
|
||||
do
|
||||
for i_{{$intf_2_var_name}} in $i_{{$intf_2_var_name}}_list
|
||||
do
|
||||
test -n "$i_{{$intf_1_var_name}}" && test -n "$i_{{$intf_2_var_name}}" && {{$command}}
|
||||
done
|
||||
done
|
||||
{{endif}}
|
||||
|
||||
|
||||
@ -12,92 +12,54 @@ check_file() {
|
||||
}
|
||||
}
|
||||
|
||||
## va_num=1
|
||||
## add_addr() {
|
||||
## addr=$1
|
||||
## nm=$2
|
||||
## dev=$3
|
||||
##
|
||||
## type=""
|
||||
## aadd=""
|
||||
##
|
||||
## L=`$IP -4 link ls $dev | head -n1`
|
||||
## if test -n "$L"; then
|
||||
## OIFS=$IFS
|
||||
## IFS=" /:,<"
|
||||
## set $L
|
||||
## type=$4
|
||||
## IFS=$OIFS
|
||||
## if test "$type" = "NO-CARRIER"; then
|
||||
## type=$5
|
||||
## fi
|
||||
##
|
||||
## L=`$IP -4 addr ls $dev to $addr | grep inet | grep -v :`
|
||||
## if test -n "$L"; then
|
||||
## OIFS=$IFS
|
||||
## IFS=" /"
|
||||
## set $L
|
||||
## aadd=$2
|
||||
## IFS=$OIFS
|
||||
## fi
|
||||
## fi
|
||||
## if test -z "$aadd"; then
|
||||
## if test "$type" = "POINTOPOINT"; then
|
||||
## $IP -4 addr add $addr dev $dev scope global label $dev:FWB${va_num}
|
||||
## va_num=`expr $va_num + 1`
|
||||
## fi
|
||||
## if test "$type" = "BROADCAST"; then
|
||||
## $IP -4 addr add $addr/$nm dev $dev brd + scope global label $dev:FWB${va_num}
|
||||
## va_num=`expr $va_num + 1`
|
||||
## fi
|
||||
## fi
|
||||
## }
|
||||
|
||||
getInterfaceVarName() {
|
||||
echo $1 | sed 's/\./_/'
|
||||
}
|
||||
|
||||
getaddr() {
|
||||
##
|
||||
## getaddr6() reimplementation idea courtesy Juergen Kammer
|
||||
## <j.kammer@eurodata.de> See ticket #651
|
||||
## http://svn.vk.crocodile.org:8765/fwbuilder/ticket/651
|
||||
##
|
||||
## Can not use awk substr() function as originally suggested by
|
||||
## Juergen because of the difference in behavior between GNU awk and
|
||||
## mawk (a bug?). GNU awk substr() returns +1 character while mawk
|
||||
## returns n characters. Tested with GNU awk v3.1.5 (CentOS 5.2) and
|
||||
## mawk v1.3.3 (Ubuntu Jaunty)
|
||||
##
|
||||
## This sed command has been tested with GNU sed v4.1.5 and busybox v1.00
|
||||
##
|
||||
## getaddr has been reimplemented to return list of all ipv4 addresses
|
||||
## of the interface. This is different from its behavior in fwbuilder
|
||||
## v2 and v3 where it returned only the first address.
|
||||
##
|
||||
|
||||
getaddr_internal() {
|
||||
dev=$1
|
||||
name=$2
|
||||
##
|
||||
## originally this command looked like this:
|
||||
## $IP -4 addr ls $dev to $addr | grep inet | grep -E "$dev$"`
|
||||
##
|
||||
## i.e. it looked for a line that ends with "$dev":
|
||||
## inet 10.3.14.40/24 brd 10.3.14.255 scope global eth0
|
||||
## as opposed to
|
||||
## inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0:1
|
||||
##
|
||||
## It turns out, some busybox-based systems have grep compiled w/o
|
||||
## support for regular expressions. Using "grep -v :" seems to be an
|
||||
## easy way to filter out secondary addresses without using regex
|
||||
##
|
||||
L=`$IP -4 addr show dev $dev | grep inet | grep -v :`
|
||||
af=$3
|
||||
L=$($IP $af addr show dev $dev | sed -n '/inet/{s!.*inet6* !!;s!/.*!!p}')
|
||||
test -z "$L" && {
|
||||
eval "$name=''"
|
||||
return
|
||||
}
|
||||
OIFS=$IFS
|
||||
IFS=" /"
|
||||
set $L
|
||||
eval "$name=$2"
|
||||
IFS=$OIFS
|
||||
eval "${name}_list=\"$L\""
|
||||
}
|
||||
|
||||
##
|
||||
## This function reads all ipv4 addresses of interface (arg 1) and
|
||||
## assignes the list to the variable which name is given as arg 2.
|
||||
##
|
||||
getaddr() {
|
||||
getaddr_internal $1 $2 "-4"
|
||||
}
|
||||
|
||||
##
|
||||
## This function reads all ipv6 addresses of interface (arg 1) and
|
||||
## assignes the list to the variable which name is given as arg 2.
|
||||
##
|
||||
getaddr6() {
|
||||
dev=$1
|
||||
name=$2
|
||||
L=`$IP -6 addr show dev $dev | grep inet6 | grep -v :`
|
||||
test -z "$L" && {
|
||||
eval "$name=''"
|
||||
return
|
||||
}
|
||||
OIFS=$IFS
|
||||
IFS=" /"
|
||||
set $L
|
||||
eval "$name=$2"
|
||||
IFS=$OIFS
|
||||
getaddr_internal $1 $2 "-6"
|
||||
}
|
||||
|
||||
# function getinterfaces is used to process wildcard interfaces
|
||||
@ -112,24 +74,6 @@ getinterfaces() {
|
||||
done
|
||||
}
|
||||
|
||||
## increment ip address
|
||||
## incaddr() {
|
||||
## n1=$4
|
||||
## n2=$3
|
||||
## n3=$2
|
||||
## n4=$1
|
||||
##
|
||||
## vn1=`eval "echo \\$$n1"`
|
||||
##
|
||||
## R=`expr $vn1 \< 255`
|
||||
## if test $R = "1"; then
|
||||
## eval "$n1=`expr $vn1 + 1`"
|
||||
## else
|
||||
## eval "$n1=0"
|
||||
## incaddr XX $n4 $n3 $n2
|
||||
## fi
|
||||
## }
|
||||
|
||||
diff_intf() {
|
||||
func=$1
|
||||
list1=$2
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
<li><a href="#cluster">Support for High Availability configurations</a></li>
|
||||
<li><a href="#pix_cluster">Cluster configuration for PIX</a></li>
|
||||
<li><a href="#bridge">Changes in the support for bridging firewalls</a></li>
|
||||
<li><a href="#iptables">Changes in the policy compiler for iptables</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
@ -437,3 +438,22 @@ rule sets of this object rather than in the actual firewalls.
|
||||
|
||||
|
||||
|
||||
<a name="iptables"></a>
|
||||
<h2>Changes in the policy compiler for iptables</h2>
|
||||
|
||||
<p>
|
||||
When an <b>interface with dynamic address</b> is used in a policy or
|
||||
NAT rule, compiler generates shell script to read its ip addresses
|
||||
at the time of execution, assigns them to temporary shell variables
|
||||
and uses them in rules. In previous versions (fwbuilder v2 and v3)
|
||||
only the first IPv4 address of an inetrface was used. V4 uses all
|
||||
IPv4 and IPv6 addresses of the interface by creating a shell "for"
|
||||
loop in the script. Note that support for dynamic IPv6 addresses
|
||||
was broken in v3 completely, it was fixed in v4.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Policy compiler for iptables can generate shell commands to
|
||||
configure bridge, bonding and vlan interfaces (see above).
|
||||
</p>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user