1
0
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:
Vadim Kurland 2009-12-02 04:27:09 +00:00
parent 758ce50c13
commit 488a50251e
7 changed files with 7872 additions and 6500 deletions

View File

@ -1 +1 @@
#define BUILD_NUM 1992
#define BUILD_NUM 1996

View File

@ -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()

View File

@ -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);

View 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}}

View File

@ -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

View File

@ -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