From 1460fef57f6f782603e20d3315276c50203d288b Mon Sep 17 00:00:00 2001 From: Vadim Kurland Date: Tue, 8 Feb 2011 14:10:33 -0800 Subject: [PATCH] fixes #2042 add configlet and shell functions to manage bridge interfaces via shell script on OpenBSD and FreeBSD --- doc/ChangeLog | 7 + src/pflib/OSConfigurator_bsd.cpp | 30 +- src/pflib/OSConfigurator_bsd_interfaces.cpp | 4 +- src/pflib/OSConfigurator_freebsd.cpp | 1 + src/res/configlets/bsd/update_bridge | 125 +++++ src/res/configlets/bsd/update_carp | 2 +- src/res/configlets/bsd/update_pfsync | 2 +- src/res/configlets/bsd/update_vlans | 4 +- test/pf/objects-for-regression-tests.fwb | 481 +++++++++++++++++++- 9 files changed, 649 insertions(+), 7 deletions(-) create mode 100644 src/res/configlets/bsd/update_bridge diff --git a/doc/ChangeLog b/doc/ChangeLog index dd3af369a..03c2f16b1 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,12 @@ 2011-02-08 vadim + * configlets/bsd/update_bridge: fixes #2042 "add configlet and + shell functions to manage bridge interfaces via shell script on + OpenBSD and FreeBSD". Bridge interfaces are managed incrementally, + that is, the script creates and destroys them as needed, then adds + or removes bridge ports, to bring bridge configuration in sync + with what is defined in fwbuilder GUI. + * CompilerDriver_pf_run.cpp (run): fixes #2054 "Add support for load anchor PF command". Instead of loading anchors using "pfctl -a anchor -f file" command in the .fw initialization script, now diff --git a/src/pflib/OSConfigurator_bsd.cpp b/src/pflib/OSConfigurator_bsd.cpp index 627cdd2d1..0e2a1715d 100644 --- a/src/pflib/OSConfigurator_bsd.cpp +++ b/src/pflib/OSConfigurator_bsd.cpp @@ -33,6 +33,7 @@ #include "fwbuilder/IPv6.h" #include "fwbuilder/FailoverClusterGroup.h" #include "fwbuilder/StateSyncClusterGroup.h" +#include "fwbuilder/XMLTools.h" #include "interfaceProperties.h" #include "interfacePropertiesObjectFactory.h" @@ -89,7 +90,9 @@ string OSConfigurator_bsd::printFunctions() { ostringstream ostr; - FWOptions* options=fw->getOptionsObject(); + FWOptions* options = fw->getOptionsObject(); + string host_os = fw->getStr("host_OS"); + string version = fw->getStr("version"); Configlet functions(fw, "bsd", "shell_functions"); functions.removeComments(); @@ -132,6 +135,8 @@ string OSConfigurator_bsd::printFunctions() { Configlet update_addresses(fw, "bsd", "update_addresses"); update_addresses.removeComments(); + update_addresses.setVariable("freebsd", host_os == "freebsd"); + update_addresses.setVariable("openbsd", host_os == "openbsd"); ostr << update_addresses.expand().toStdString(); } @@ -139,13 +144,34 @@ string OSConfigurator_bsd::printFunctions() { Configlet update_vlans(fw, "bsd", "update_vlans"); update_vlans.removeComments(); + update_vlans.setVariable("freebsd", host_os == "freebsd"); + update_vlans.setVariable("openbsd", host_os == "openbsd"); ostr << update_vlans.expand().toStdString(); } + if (options->getBool("configure_bridge_interfaces")) + { + Configlet update_bridge(fw, "bsd", "update_bridge"); + update_bridge.removeComments(); + update_bridge.setVariable("freebsd", host_os == "freebsd"); + if (host_os == "openbsd") + { + update_bridge.setVariable("openbsd", true); + update_bridge.setVariable("openbsd_lt_47", + XMLTools::version_compare(version, "4.7")<0); + update_bridge.setVariable("openbsd_ge_47", + XMLTools::version_compare(version, "4.7")>=0); + } + + ostr << update_bridge.expand().toStdString(); + } + if ( options->getBool("configure_carp_interfaces") ) { Configlet update_carp(fw, "bsd", "update_carp"); update_carp.removeComments(); + update_carp.setVariable("freebsd", host_os == "freebsd"); + update_carp.setVariable("openbsd", host_os == "openbsd"); ostr << update_carp.expand().toStdString(); } @@ -153,6 +179,8 @@ string OSConfigurator_bsd::printFunctions() { Configlet update_pfsync(fw, "bsd", "update_pfsync"); update_pfsync.removeComments(); + update_pfsync.setVariable("freebsd", host_os == "freebsd"); + update_pfsync.setVariable("openbsd", host_os == "openbsd"); ostr << update_pfsync.expand().toStdString(); } diff --git a/src/pflib/OSConfigurator_bsd_interfaces.cpp b/src/pflib/OSConfigurator_bsd_interfaces.cpp index f505afb0b..5de8c900e 100644 --- a/src/pflib/OSConfigurator_bsd_interfaces.cpp +++ b/src/pflib/OSConfigurator_bsd_interfaces.cpp @@ -361,6 +361,8 @@ void OSConfigurator_bsd::summaryConfigLineIP(QStringList , bool ) void OSConfigurator_bsd::interfaceConfigLineIP( Interface *iface, list > all_addresses) { + if (iface->isDyn()) return; + QStringList arg1; arg1.push_back(iface->getName().c_str()); @@ -438,7 +440,7 @@ void OSConfigurator_bsd::interfaceConfigLineBridge(Interface *iface, QStringList bridge_port_names) { interface_configuration_lines << - QString("update_bridge_interface \"%1 %2\"") + QString("update_bridge_interface %1 \"%2\"") .arg(iface->getName().c_str()) .arg(bridge_port_names.join(" ")); } diff --git a/src/pflib/OSConfigurator_freebsd.cpp b/src/pflib/OSConfigurator_freebsd.cpp index 8e24ec3c0..bc8f76ba9 100644 --- a/src/pflib/OSConfigurator_freebsd.cpp +++ b/src/pflib/OSConfigurator_freebsd.cpp @@ -137,6 +137,7 @@ void OSConfigurator_freebsd::interfaceConfigLineIP( if (iface->isDyn()) { ifconfig_lines[interface_name] << "DHCP"; + return; } int ipv4_alias_counter = -2; diff --git a/src/res/configlets/bsd/update_bridge b/src/res/configlets/bsd/update_bridge new file mode 100644 index 000000000..d2b081a98 --- /dev/null +++ b/src/res/configlets/bsd/update_bridge @@ -0,0 +1,125 @@ +## -*- mode: shell-script; -*- +## +## To be able to make changes to the part of configuration created +## from this configlet you need to copy this file to the directory +## fwbuilder/configlets/linux24/ in your home directory and modify it. +## Double "##" comments are removed during processing but single "#" +## comments are be retained and appear in the generated script. Empty +## lines are removed as well. +## +## Configlets support simple macro language with these constructs: +## {{$var}} is variable expansion +## {{if var}} is conditional operator. +## + +{{if openbsd_lt_47}} +BRCONFIG="brconfig" +{{endif}} + +{{if openbsd_ge_47}} +BRCONFIG="$IFCONFIG" +{{endif}} + +{{if freebsd}} +BRCONFIG="$IFCONFIG" +{{endif}} + +missing_port() { + intf=$1 + cmd=$2 + + oldIFS=$IFS + IFS="@" + set $intf + port=$1 + bridge_interface=$2 + IFS=$oldIFS + + echo "# Updating bridge configuration: $bridge_interface $cmd $port" + $FWBDEBUG $BRCONFIG $bridge_interface $cmd $port + test "$cmd" = "addm" && $FWBDEBUG $IFCONFIG $port up +} + +## update_bridge br0 "eth2 eth3" +update_bridge_interface() { + bridge_interface=$1 + shift + + FWB_PORTS="" + CURRENT_PORTS="" + + FWB_PORTS=$( + for subint in $*; do + echo "${subint}@$bridge_interface" + done | sort + ) + + # this is really redundant because we create missing bridge + # interfaces in sync_bridge_interfaces. However will leave this + # here so that function update_bridge can be used without prior + # call to sync_bridge_interfaces The difference is that + # sync_bridge_interfaces also deletes bridge interfaces that exist + # on the machine but are missing in fwbuilder confgiuration. The + # update_bridge function can only add bridge interfaces. + $BRCONFIG $bridge_interface >/dev/null 2>&1 || { + echo "# Creating bridge interface $bridge_interface" + $FWBDEBUG $IFCONFIG $bridge_interface create + $FWBDEBUG $IFCONFIG $bridge_interface up + } + + PORTS=$( + $BRCONFIG $bridge_interface | awk '($1~/member:/) { print $2; }' + ) + + test -n "$PORTS" && { + CURRENT_PORTS=$( + for subint in $PORTS; do + echo "${subint}@$bridge_interface" + done | sort + ) + } + + # first delete bridge ports, then add. This way, if an interface + # moves from one bridge to another, we remove it first and then + # add. It would not work if we tried to add it first, brctl issues + # an error: + # device eth2 is already a member of a bridge; can't enslave it to bridge br1. + # + diff_intf missing_port "$CURRENT_PORTS" "$FWB_PORTS" deletem + diff_intf missing_port "$FWB_PORTS" "$CURRENT_PORTS" addm +} + +## This function synchronizes bridge interfaces between fwbuilder objects +## and actual configuration of the firewall machine. Birgde interfaces not +## listed as arguments will be deleted and those in the arguments will be +## created if missing. +## +## NOTE: we have to delete and create bridge interfaces before we add +## bridge ports to them because if a bridge interface that was not +## configured in fwbuilder existed before this script ran, its bridge +## ports could not be added to other bridges. This bridge interface +## should be deleted first. +## +## sync_bridge_interfaces bridge0 bridge1 + +sync_bridge_interfaces() { + $BRCONFIG -a | awk -F: -v IGNORED="$*" \ + 'BEGIN { + split(IGNORED,ignored_arr); + for (a in ignored_arr) {ignored_dict[ignored_arr[a]]=1;} + } + ($1 ~ /^bridge[0-9]/ && !($1 in ignored_dict)) {print $1;}' | \ + while read brintf; do + echo "# Deleting bridge interface $brintf" + $FWBDEBUG $IFCONFIG $brintf down + $FWBDEBUG $IFCONFIG $brintf destroy + done + + for brint in $*; do + $BRCONFIG $brint >/dev/null 2>&1 || { + echo "# Creating bridge interface $brintf" + $FWBDEBUG $IFCONFIG $brint create + $FWBDEBUG $IFCONFIG $brint up + } + done +} diff --git a/src/res/configlets/bsd/update_carp b/src/res/configlets/bsd/update_carp index bd5d63140..f3ae1fb0f 100644 --- a/src/res/configlets/bsd/update_carp +++ b/src/res/configlets/bsd/update_carp @@ -27,7 +27,7 @@ ## sync_carp_interfaces carp0 carp1 sync_carp_interfaces() { - $IFCONFIG -A | awk -v IGNORED="$*" \ + $IFCONFIG {{if openbsd}}-A{{endif}} | awk -v IGNORED="$*" \ 'BEGIN { split(IGNORED,ignored_arr); for (a in ignored_arr) {ii=ignored_arr[a]":"; ignored_dict[ii]=1;} diff --git a/src/res/configlets/bsd/update_pfsync b/src/res/configlets/bsd/update_pfsync index 1358571d0..db094c85b 100644 --- a/src/res/configlets/bsd/update_pfsync +++ b/src/res/configlets/bsd/update_pfsync @@ -30,7 +30,7 @@ ## does not depend on this assumption. sync_pfsync_interfaces() { - $IFCONFIG -A | awk -v IGNORED="$*" \ + $IFCONFIG {{if openbsd}}-A{{endif}} | awk -v IGNORED="$*" \ 'BEGIN { split(IGNORED,ignored_arr); for (a in ignored_arr) {ii=ignored_arr[a]":"; ignored_dict[ii]=1;} diff --git a/src/res/configlets/bsd/update_vlans b/src/res/configlets/bsd/update_vlans index 893aada71..cbe71966a 100644 --- a/src/res/configlets/bsd/update_vlans +++ b/src/res/configlets/bsd/update_vlans @@ -52,7 +52,7 @@ parse_fwb_vlans() { parse_current_vlans() { vlan_parent_interface=$1 - $IFCONFIG -A | grep 'vlan: ' | sed 's/priority:.*parent interface://' | \ + $IFCONFIG {{if openbsd}}-A{{endif}} | grep 'vlan: ' | sed 's/priority:.*parent interface://' | \ while read x vlan_id parent do test "$parent" = "$vlan_parent_interface" && echo "vlan$vlan_id@$parent" @@ -79,7 +79,7 @@ update_vlans_of_interface() { } sync_vlan_interfaces() { - $IFCONFIG -A | awk -v IGNORED="$*" \ + $IFCONFIG {{if openbsd}}-A{{endif}} | awk -v IGNORED="$*" \ 'BEGIN { split(IGNORED,ignored_arr); for (a in ignored_arr) {ii=ignored_arr[a]":"; ignored_dict[ii]=1;} diff --git a/test/pf/objects-for-regression-tests.fwb b/test/pf/objects-for-regression-tests.fwb index af4e32d0c..2fd05bb37 100644 --- a/test/pf/objects-for-regression-tests.fwb +++ b/test/pf/objects-for-regression-tests.fwb @@ -1,6 +1,6 @@ - + @@ -21642,6 +21642,485 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +