1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-25 04:37:22 +01:00

* OSConfigurator_bsd.cpp (OSConfigurator_bsd::updateAddressesOfInterfaceCall):

New feature: incremental IP address management for OpenBSD and
FreeBSD. Generated script adds and removes ipv4 and ipv6 addresses
of interfaces as needed. When user adds an address in the
fwbuilder object, the script adds it. Second run of the same script
does nothing. If user removes an address in fwbuilder, generated
script removes it from the interfaces to bring actual configuration
of the machine in sync with fwbuilder objects.
This commit is contained in:
Vadim Kurland 2010-02-13 05:15:38 +00:00
parent fcceaf05f5
commit 01a79aeed5
7 changed files with 250 additions and 73 deletions

View File

@ -1 +1 @@
#define BUILD_NUM 2513
#define BUILD_NUM 2517

View File

@ -1,3 +1,14 @@
2010-02-12 vadim <vadim@vk.crocodile.org>
* OSConfigurator_bsd.cpp (OSConfigurator_bsd::updateAddressesOfInterfaceCall):
New feature: incremental IP address management for OpenBSD and
FreeBSD. Generated script adds and removes ipv4 and ipv6 addresses
of interfaces as needed. When user adds an address in the
fwbuilder object, the script adds it. Second run of the same script
does nothing. If user removes an address in fwbuilder, generated
script removes it from the interfaces to bring actual configuration
of the machine in sync with fwbuilder objects.
2010-02-10 yalovoy <yalovoy@gmail.com>
* src/gui/RuleSetModel.cpp: fixes #1223: GUI crash while adding a host to a group
To reproduce:

View File

@ -59,45 +59,73 @@ string OSConfigurator_bsd::printKernelVarsCommands()
return "";
}
string OSConfigurator_bsd::updateAddressesOfInterfaceCall(
Interface *iface, list<pair<InetAddr,InetAddr> > all_addresses)
{
QStringList arg1;
arg1.push_back(iface->getName().c_str());
for (list<pair<InetAddr,InetAddr> >::iterator j = all_addresses.begin();
j != all_addresses.end(); ++j)
{
InetAddr ipaddr = j->first;
InetAddr ipnetm = j->second;
if (ipaddr.isV6())
arg1.push_back(QString("%1/%2").arg(ipaddr.toString().c_str())
.arg(ipnetm.getLength()));
else
{
/*
on OpenBSD ifconfig prints netmask of ipv4 addresses in hex
# ifconfig em0
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:0c:29:83:4d:2f
media: Ethernet autoselect (1000baseT full-duplex,master)
status: active
inet 10.1.1.50 netmask 0xffffff00 broadcast 10.1.1.255
inet6 fe80::20c:29ff:fe83:4d2f%em0 prefixlen 64 scopeid 0x2
*/
int nbits = ipnetm.getLength();
uint32_t netm = 0;
while (nbits)
{
netm = netm >> 1;
netm |= 1<<31;
nbits--;
}
arg1.push_back(QString("%1/0x%2")
.arg(ipaddr.toString().c_str())
.arg(netm, -8, 16));
}
}
return string("update_addresses_of_interface ") +
"\"" +
arg1.join(" ").toStdString() +
"\"" +
" \"\"";
}
void OSConfigurator_bsd::addVirtualAddressForNAT(const Network*)
{
}
/**
* This method is called from NATCompiler_pf::addVirtualAddress::processNext()
*/
void OSConfigurator_bsd::addVirtualAddressForNAT(const Address *addr)
{
if (virtual_addresses.empty() ||
find(virtual_addresses.begin(),
virtual_addresses.end(),
*(addr->getAddressPtr())) == virtual_addresses.end())
FWObject *iaddr = findAddressFor(addr, fw );
if (iaddr!=NULL)
{
FWObject *iaddr = findAddressFor(addr, fw );
if (iaddr!=NULL)
{
Address *iaddr_addr = Address::cast(iaddr);
assert(iaddr_addr!=NULL);
const InetAddr *ipaddr = iaddr_addr->getAddressPtr();
const InetAddr *ipnetm = iaddr_addr->getNetmaskPtr();
Interface *iface = Interface::cast(iaddr->getParent());
assert(iface!=NULL);
if (ipaddr->isV6())
{
output << "add_addr6 " << addr->getAddressPtr()->toString() << " "
<< ipnetm->getLength() << " "
<< iface->getName() << endl;
} else
{
output << "add_addr " << addr->getAddressPtr()->toString() << " "
<< ipnetm->toString() << " "
<< iface->getName() << endl;
}
virtual_addresses.push_back(*(addr->getAddressPtr()));
} else
warning("Can not add virtual address " +
addr->getAddressPtr()->toString() );
}
virtual_addresses.insert(addr);
} else
warning("Can not add virtual address " +
addr->getAddressPtr()->toString() );
}
int OSConfigurator_bsd::prolog()
@ -107,6 +135,8 @@ int OSConfigurator_bsd::prolog()
string OSConfigurator_bsd::printFunctions()
{
ostringstream ostr;
FWOptions* options=fw->getOptionsObject();
Configlet functions(fw, "bsd", "shell_functions");
@ -144,7 +174,16 @@ string OSConfigurator_bsd::printFunctions()
} else
functions.setVariable("get_dyn_addr_commands", "");
return functions.expand().toStdString();
ostr << functions.expand().toStdString();
if ( options->getBool("configure_interfaces") )
{
Configlet update_addresses(fw, "bsd", "update_addresses");
update_addresses.removeComments();
ostr << update_addresses.expand().toStdString();
}
return ostr.str();
}
string OSConfigurator_bsd::configureInterfaces()
@ -169,30 +208,39 @@ string OSConfigurator_bsd::configureInterfaces()
list<FWObject*> all_ipv6 = iface->getByType(IPv6::TYPENAME);
all_addr.insert(all_addr.begin(), all_ipv6.begin(), all_ipv6.end());
const InetAddr *netmask = iface->getNetmaskPtr();
list<pair<InetAddr,InetAddr> > all_addresses;
for (list<FWObject*>::iterator j = all_addr.begin();
j != all_addr.end(); ++j)
j != all_addr.end(); ++j)
{
Address *iaddr = Address::cast(*j);
const InetAddr *ipaddr = iaddr->getAddressPtr();
const InetAddr *ipnetm = iaddr->getNetmaskPtr();
if (ipaddr->isV6())
{
ostr << "add_addr6 "
<< ipaddr->toString() << " "
<< ipnetm->getLength() << " "
<< iface->getName() << endl;
} else
{
ostr << "add_addr "
<< ipaddr->toString() << " "
<< ipnetm->toString() << " "
<< iface->getName() << endl;
}
virtual_addresses.push_back(*ipaddr);
all_addresses.push_back(
pair<InetAddr,InetAddr>(*ipaddr, *ipnetm));
}
set<const Address*>::iterator it;
for (it=virtual_addresses.begin(); it!=virtual_addresses.end(); ++it)
{
const Address *addr = *it;
FWObject *iaddr = findAddressFor(addr, fw );
if (iaddr!=NULL)
{
Interface *iface_2 = Interface::cast(iaddr->getParent());
if (iface_2 == iface)
{
all_addresses.push_back(
pair<InetAddr,InetAddr>(
*(addr->getAddressPtr()), *netmask));
}
}
}
ostr << updateAddressesOfInterfaceCall(iface, all_addresses) << endl;
}
ostr << endl;
}

View File

@ -30,6 +30,8 @@
#include "fwcompiler/OSConfigurator.h"
#include <set>
#include <QString>
@ -41,11 +43,15 @@ namespace fwcompiler {
class OSConfigurator_bsd : public OSConfigurator {
protected:
std::vector<libfwbuilder::InetAddr> virtual_addresses;
std::set<const libfwbuilder::Address*> virtual_addresses;
void setKernelVariable(libfwbuilder::Firewall *fw,
const std::string &var_name,
Configlet *configlet);
std::string updateAddressesOfInterfaceCall(
libfwbuilder::Interface *iface,
std::list<std::pair<libfwbuilder::InetAddr,libfwbuilder::InetAddr> > all_addresses);
public:
virtual ~OSConfigurator_bsd() {};

View File

@ -16,26 +16,18 @@ log() {
test -x "$LOGGER" && $LOGGER -p info "$1"
}
add_addr() {
addr=$1
nm=$2
dev=$3
( ifconfig $dev | egrep -q "inet +${addr} " ) ||
{
echo "$dev: $addr/$nm"
ifconfig $dev inet $addr netmask $nm alias
}
}
add_addr6() {
addr=$1
nm=$2
dev=$3
( ifconfig $dev | egrep -q "inet6 +${addr} " ) ||
{
echo "$dev: $addr/$nm"
ifconfig $dev inet6 $addr prefixlen $nm alias
}
diff_intf() {
func=$1
list1=$2
list2=$3
cmd=$4
for intf in $list1
do
echo $list2 | grep -q $intf || {
# $vlan is absent in list 2
$func $intf $cmd
}
done
}
{{if dyn_addr}}

View File

@ -0,0 +1,119 @@
## -*- mode: shell-script; -*-
##
## Lines that start with "##" will be removed before this code is
## added to the generated script. Regular shell comments can be added
## using single "#", these will appear in the script.
##
############ add or remove ip addresses of interfaces #######################
## address (argument 1) is in the form of address/netmask, where
## netmask should be hex represenatation matching netmask in the
## output of ifconfig for ipv4 address. For ipv6 addresses netmask
## part should be given as prefix length.
missing_address() {
address=$1
cmd=$2
oldIFS=$IFS
IFS="@"
set $address
addr=$1
interface=$2
IFS=$oldIFS
if echo "$addr" | grep -q ':'
then
inet="inet6"
addr=$(echo "$addr" | sed 's!/! prefixlen !')
else
inet="inet"
addr=$(echo "$addr" | sed 's!/! netmask !')
fi
parameter=""
test "$cmd" = "add" && {
echo "# Adding ip address: $interface $addr"
parameter="alias"
}
test "$cmd" = "del" && {
echo "# Removing ip address: $interface $addr"
parameter="delete"
}
$FWBDEBUG $IFCONFIG $interface $inet $addr $parameter
$FWBDEBUG $IFCONFIG $interface up
}
##
## The list of current addresses is taken using "ifconfig $interface"
## command. Second argument defines address scrope; it should be in
## the form of the matching regex such as "scope global" or "scope
## .*". Unfortunately ifconfig prints "scopeid" for link and host
## scopes but does not print any "scopeid" parameter for the global
## scope (tested on OpenBSD 4.2). This means I have to invert the
## regex match logic and skip addresses with given scope (this is
## different from how this function works for addresses on Linux). If
## any non-empty scope string is given as second argument, this
## function will skip addresses with this scope. If this argument is
## an empty string, this function returns all addresses.
##
list_addresses_by_scope() {
interface=$1
scope=$2
ignore_list=$3
scope_regex="1"
if test -n "$scope"; then scope_regex=" \$0 !~ \"$scope\" "; fi
$IFCONFIG $interface | sed "s/%$interface//" | \
awk -v IGNORED="$ignore_list" \
"BEGIN {
split(IGNORED,ignored_arr);
for (a in ignored_arr) {ignored_dict[ignored_arr[a]]=1;}
}
(/inet |inet6 / && $scope_regex && !(\$2 in ignored_dict)) {printf \"%s/%s\n\",\$2,\$4;}" | \
while read addr; do
echo "${addr}@$interface"
done | sort
}
## arg 1 is like "pcn1 1.1.1.1/24 2.2.2.2/24 fe80::20c:29ff:fef6:bea0/64"
## arg 2 is "3.3.3.3/24 4.4.4.4/24" - list of addresses we should ignore
## Using arg2 to provide list of addresses managed by heartbeat, so that
## incremental update does not delete them.
##
## Only "scope global" addreses are managed because fwbuilder script
## should not try to delete addresses configured for tunnels and IPv6
## link scope addresses (fe80::) ("scope link" or "scope host" addresses)
##
## Addresses we should ignore are dropped from the list.
##
update_addresses_of_interface() {
ignore_list=$2
set $1
interface=$1
shift
FWB_ADDRS=$(
for addr in $*; do
echo "${addr}@$interface"
done | sort
)
CURRENT_ADDRS_ALL_SCOPES=""
CURRENT_ADDRS_GLOBAL_SCOPE=""
$IFCONFIG $interface >/dev/null 2>&1 && {
CURRENT_ADDRS_ALL_SCOPES=$(list_addresses_by_scope $interface '' "$ignore_list")
CURRENT_ADDRS_GLOBAL_SCOPE=$(list_addresses_by_scope $interface 'scopeid .*' "$ignore_list")
} || {
echo "# Interface $interface does not exist"
# Stop the script if we are not in test mode
test -z "$FWBDEBUG" && exit 1
}
diff_intf missing_address "$FWB_ADDRS" "$CURRENT_ADDRS_ALL_SCOPES" add
diff_intf missing_address "$CURRENT_ADDRS_GLOBAL_SCOPE" "$FWB_ADDRS" del
}

View File

@ -13,6 +13,7 @@
##
## Set path to all utilities that we need
IFCONFIG="ifconfig"
PFCTL="{{$path_pfctl}}"
SYSCTL="{{$path_sysctl}}"
LOGGER="{{$path_logger}}"