mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-03-21 18:57:14 +01:00
501 lines
16 KiB
C++
501 lines
16 KiB
C++
/*
|
|
|
|
Firewall Builder
|
|
|
|
Copyright (C) 2002-2011 NetCitadel, LLC
|
|
|
|
Author: Vadim Kurland vadim@fwbuilder.org
|
|
|
|
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 <assert.h>
|
|
|
|
#include "OSConfigurator_freebsd.h"
|
|
#include "Configlet.h"
|
|
#include "interfaceProperties.h"
|
|
#include "interfacePropertiesObjectFactory.h"
|
|
|
|
#include "fwbuilder/Firewall.h"
|
|
#include "fwbuilder/FWOptions.h"
|
|
#include "fwbuilder/Interface.h"
|
|
#include "fwbuilder/IPv4.h"
|
|
#include "fwbuilder/FailoverClusterGroup.h"
|
|
#include "fwbuilder/StateSyncClusterGroup.h"
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
|
|
using namespace libfwbuilder;
|
|
using namespace fwcompiler;
|
|
using namespace std;
|
|
|
|
string OSConfigurator_freebsd::myPlatformName() { return "FreeBSD"; }
|
|
|
|
string OSConfigurator_freebsd::printKernelVarsCommands()
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
std::auto_ptr<Configlet> kernel_vars;
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
kernel_vars = std::auto_ptr<Configlet>(
|
|
new Configlet(fw, "freebsd", "rc_conf_kernel_vars"));
|
|
} else
|
|
{
|
|
kernel_vars = std::auto_ptr<Configlet>(
|
|
new Configlet(fw, "bsd", "kernel_vars"));
|
|
}
|
|
|
|
kernel_vars->removeComments();
|
|
setKernelVariable(fw, "freebsd_ip_forward", kernel_vars.get());
|
|
setKernelVariable(fw, "freebsd_ipv6_forward", kernel_vars.get());
|
|
setKernelVariable(fw, "freebsd_ip_sourceroute", kernel_vars.get());
|
|
//setKernelVariable(fw, "freebsd_ip_redirect", kernel_vars.get());
|
|
return kernel_vars->expand().toStdString();
|
|
}
|
|
|
|
void OSConfigurator_freebsd::setKernelVariable(Firewall *fw,
|
|
const string &var_name,
|
|
Configlet *configlet)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
string s;
|
|
s = options->getStr(var_name);
|
|
if (!s.empty())
|
|
{
|
|
configlet->setVariable(QString("have_") + var_name.c_str(), 1);
|
|
string yesno = (s=="1" || s=="on" || s=="On") ? "YES" : "NO";
|
|
configlet->setVariable(QString(var_name.c_str()),
|
|
QString(yesno.c_str()));
|
|
}
|
|
} else
|
|
OSConfigurator_bsd::setKernelVariable(fw, var_name, configlet);
|
|
}
|
|
|
|
int OSConfigurator_freebsd::prolog()
|
|
{
|
|
//printPathForAllTools("freebsd");
|
|
//printFunctions();
|
|
|
|
//processFirewallOptions();
|
|
|
|
//configureInterfaces();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void OSConfigurator_freebsd::summaryConfigLineIP(QStringList names, bool ipv6)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file") && !names.isEmpty())
|
|
{
|
|
if (ipv6)
|
|
{
|
|
interface_configuration_lines["1_should_sort_before_interfaces_"] <<
|
|
QString("ipv6_network_interfaces=\"%1\"").arg(names.join(" "));
|
|
} else
|
|
{
|
|
interface_configuration_lines["1_should_sort_before_interfaces_"] <<
|
|
QString("network_interfaces=\"%1\"").arg(names.join(" "));
|
|
}
|
|
}
|
|
}
|
|
|
|
void OSConfigurator_freebsd::interfaceConfigLineIP(
|
|
Interface *iface, list<pair<InetAddr,InetAddr> > all_addresses)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
/*
|
|
* lines in rc.conf have the following format:
|
|
*
|
|
* network_interfaces="ed0 ed1 lo0"
|
|
* ifconfig_ed0="inet 192.0.2.1 netmask 0xffffff00"
|
|
* ipv4_addrs_ed0="192.0.2.129/27 192.0.2.1-5/28"
|
|
*
|
|
*/
|
|
|
|
QString interface_name = iface->getName().c_str();
|
|
|
|
if (iface->isDyn())
|
|
{
|
|
ifconfig_lines[interface_name] << "DHCP";
|
|
return;
|
|
}
|
|
|
|
int ipv4_alias_counter = -2;
|
|
int ipv6_alias_counter = -2;
|
|
|
|
for (list<pair<InetAddr,InetAddr> >::iterator j = all_addresses.begin();
|
|
j != all_addresses.end(); ++j)
|
|
{
|
|
QString ipv4_conf_line;
|
|
QString ipv6_conf_line;
|
|
|
|
InetAddr ipaddr = j->first;
|
|
InetAddr ipnetm = j->second;
|
|
|
|
if (ipaddr.isV6())
|
|
{
|
|
ipv6_conf_line +=
|
|
QString("%1/%2")
|
|
.arg(ipaddr.toString().c_str())
|
|
.arg(ipnetm.getLength());
|
|
ipv6_alias_counter++;
|
|
} else
|
|
{
|
|
int nbits = ipnetm.getLength();
|
|
uint32_t netm = 0;
|
|
while (nbits)
|
|
{
|
|
netm = netm >> 1;
|
|
netm |= 1<<31;
|
|
nbits--;
|
|
}
|
|
|
|
ipv4_conf_line +=
|
|
QString("%1 netmask 0x%2")
|
|
.arg(ipaddr.toString().c_str())
|
|
.arg(netm, -8, 16);
|
|
|
|
ipv4_alias_counter++;
|
|
}
|
|
|
|
if (!ipv4_conf_line.isEmpty())
|
|
{
|
|
QString suffix;
|
|
if (ipv4_alias_counter>=0)
|
|
suffix = QString("_alias%1").arg(ipv4_alias_counter);
|
|
ifconfig_lines[interface_name + suffix] << ipv4_conf_line;
|
|
}
|
|
|
|
if (!ipv6_conf_line.isEmpty())
|
|
{
|
|
QString suffix;
|
|
if (ipv6_alias_counter>=0)
|
|
suffix = QString("_alias%1").arg(ipv6_alias_counter);
|
|
ipv6_ifconfig_lines[interface_name + suffix] << ipv6_conf_line;
|
|
}
|
|
}
|
|
} else
|
|
OSConfigurator_bsd::interfaceConfigLineIP(iface, all_addresses);
|
|
}
|
|
|
|
void OSConfigurator_freebsd::interfaceIfconfigLine(Interface *iface)
|
|
{
|
|
QString iface_name = iface->getName().c_str();
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
Configlet configlet(fw, "freebsd", "rc_conf_ifconfig_interface");
|
|
QString config_lines = interfaceIfconfigLineInternal(iface, &configlet);
|
|
if (!config_lines.isEmpty()) ifconfig_lines[iface_name] << config_lines;
|
|
} else
|
|
{
|
|
Configlet configlet(fw, "freebsd", "ifconfig_interface");
|
|
QString config_lines = interfaceIfconfigLineInternal(iface, &configlet);
|
|
if (!config_lines.isEmpty())
|
|
interface_configuration_lines[iface_name] << config_lines;
|
|
}
|
|
}
|
|
|
|
void OSConfigurator_freebsd::summaryConfigLineVlan(QStringList vlan_names)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
cloned_interfaces += vlan_names;
|
|
} else
|
|
interface_configuration_lines["1_should_sort_before_interfaces_"] <<
|
|
QString("sync_vlan_interfaces %1").arg(vlan_names.join(" "));
|
|
}
|
|
|
|
/*
|
|
|
|
For rc.conf format:
|
|
|
|
If a vlans_<interface> variable is set, a vlan(4) interface
|
|
will be created for each item in the list with the vlandev
|
|
argument set to interface. If a vlan interface's name is a
|
|
number, then that number is used as the vlan tag and the new
|
|
vlan interface is named interface.tag. Otherwise, the vlan
|
|
tag must be specified via a vlan parameter in the
|
|
create_args_<interface> variable.
|
|
|
|
To create a vlan device named em0.101 on em0 with the vlan
|
|
tag 101:
|
|
|
|
vlans_em0="101"
|
|
|
|
To create a vlan device named myvlan on em0 with the vlan tag
|
|
102:
|
|
|
|
vlans_em0="myvlan"
|
|
create_args_myvlan="vlan 102"
|
|
|
|
*/
|
|
void OSConfigurator_freebsd::interfaceConfigLineVlan(Interface *iface,
|
|
QStringList vlan_names)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
QString iface_name = iface->getName().c_str();
|
|
// the "vlans_em2="vlan101 vlan102" will appear next to other lines
|
|
// intended for interface em2
|
|
interface_configuration_lines[iface_name] <<
|
|
QString("vlans_%1=\"%2\"").arg(iface->getName().c_str())
|
|
.arg(vlan_names.join(" "));
|
|
|
|
foreach(QString vlan_intf_name, vlan_names)
|
|
{
|
|
std::auto_ptr<interfaceProperties> int_prop(
|
|
interfacePropertiesObjectFactory::getInterfacePropertiesObject(
|
|
fw->getStr("host_OS")));
|
|
QString parent_name_from_regex;
|
|
int vlan_id;
|
|
if (int_prop->parseVlan(vlan_intf_name,
|
|
&parent_name_from_regex, &vlan_id))
|
|
{
|
|
interface_configuration_lines[iface_name] <<
|
|
QString("create_args_%1=\"vlan %2 vlandev %3\"")
|
|
.arg(vlan_intf_name).arg(vlan_id).arg(iface->getName().c_str());
|
|
}
|
|
}
|
|
|
|
} else
|
|
OSConfigurator_bsd::interfaceConfigLineVlan(iface, vlan_names);
|
|
}
|
|
|
|
void OSConfigurator_freebsd::summaryConfigLineBridge(QStringList bridge_names)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
cloned_interfaces += bridge_names;
|
|
} else
|
|
OSConfigurator_bsd::summaryConfigLineBridge(bridge_names);
|
|
}
|
|
|
|
/*
|
|
|
|
For rc.conf format:
|
|
|
|
Consider a system with two 4-port Ethernet boards. The following will
|
|
cause a bridge consisting of all 8 ports with Rapid Spanning Tree enabled
|
|
to be created:
|
|
|
|
ifconfig bridge0 create
|
|
ifconfig bridge0 \
|
|
addm fxp0 stp fxp0 \
|
|
addm fxp1 stp fxp1 \
|
|
addm fxp2 stp fxp2 \
|
|
addm fxp3 stp fxp3 \
|
|
addm fxp4 stp fxp4 \
|
|
addm fxp5 stp fxp5 \
|
|
addm fxp6 stp fxp6 \
|
|
addm fxp7 stp fxp7 \
|
|
up
|
|
|
|
The bridge can be used as a regular host interface at the same time as
|
|
bridging between its member ports. In this example, the bridge connects
|
|
em0 and em1, and will receive its IP address through DHCP:
|
|
|
|
cloned_interfaces="bridge0"
|
|
ifconfig_bridge0="addm em0 addm em1 DHCP"
|
|
ifconfig_em0="up"
|
|
ifconfig_em1="up"
|
|
|
|
|
|
Refernce:
|
|
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/network-bridging.html
|
|
|
|
TODO: STP support should be optional
|
|
|
|
*/
|
|
void OSConfigurator_freebsd::interfaceConfigLineBridge(Interface *iface,
|
|
QStringList bridge_port_names)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
FWOptions *ifopt = iface->getOptionsObject();
|
|
assert(ifopt != NULL);
|
|
|
|
bool enable_stp = ifopt->getBool("enable_stp");
|
|
|
|
QStringList outp;
|
|
QStringList bp;
|
|
foreach(QString bridge_port, bridge_port_names)
|
|
{
|
|
bp << QString("addm %1 %2 %3")
|
|
.arg(bridge_port).arg((enable_stp)?"stp":"").arg(bridge_port);
|
|
}
|
|
|
|
bp << "up";
|
|
|
|
ifconfig_lines[iface->getName().c_str()] << bp.join(" ");
|
|
|
|
foreach(QString bridge_port, bridge_port_names)
|
|
{
|
|
ifconfig_lines[bridge_port] << "up";
|
|
}
|
|
|
|
interface_configuration_lines[iface->getName().c_str()] << outp.join("\n");
|
|
} else
|
|
OSConfigurator_bsd::interfaceConfigLineBridge(iface, bridge_port_names);
|
|
}
|
|
|
|
|
|
void OSConfigurator_freebsd::summaryConfigLineCARP(QStringList carp_names)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
cloned_interfaces += carp_names;
|
|
} else
|
|
OSConfigurator_bsd::summaryConfigLineCARP(carp_names);
|
|
}
|
|
|
|
void OSConfigurator_freebsd::interfaceConfigLineCARP(Interface *iface,
|
|
FWObject *failover_group)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
QString configlet_name = "carp_interface";
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
configlet_name = "rc_conf_carp_interface";
|
|
}
|
|
|
|
Configlet configlet(fw, "freebsd", configlet_name);
|
|
interfaceConfigLineCARPInternal(iface, failover_group, &configlet);
|
|
}
|
|
|
|
void OSConfigurator_freebsd::summaryConfigLinePfsync(bool have_pfsync)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
interface_configuration_lines["pfsync0"] << "pfsync_enable=\"YES\"";
|
|
} else
|
|
OSConfigurator_bsd::summaryConfigLinePfsync(have_pfsync);
|
|
}
|
|
|
|
/*
|
|
in rc.conf format:
|
|
|
|
pfsync_enable
|
|
(bool) Set to ``NO'' by default. Setting this to ``YES''
|
|
enables exposing pf(4) state changes to other hosts over the
|
|
network by means of pfsync(4). The pfsync_syncdev variable
|
|
must also be set then.
|
|
|
|
pfsync_syncdev
|
|
(str) Empty by default. This variable specifies the name of
|
|
the network interface pfsync(4) should operate through. It
|
|
must be set accordingly if pfsync_enable is set to ``YES''.
|
|
|
|
pfsync_syncpeer
|
|
(str) Empty by default. This variable is optional. By
|
|
default, state change messages are sent out on the synchroni-
|
|
sation interface using IP multicast packets. The protocol is
|
|
IP protocol 240, PFSYNC, and the multicast group used is
|
|
224.0.0.240. When a peer address is specified using the
|
|
pfsync_syncpeer option, the peer address is used as a desti-
|
|
nation for the pfsync traffic, and the traffic can then be
|
|
protected using ipsec(4). See the pfsync(4) manpage for more
|
|
details about using ipsec(4) with pfsync(4) interfaces.
|
|
|
|
pfsync_ifconfig
|
|
(str) Empty by default. This variable can contain additional
|
|
options to be passed to the ifconfig(8) command used to set
|
|
up pfsync(4).
|
|
*/
|
|
|
|
void OSConfigurator_freebsd::interfaceConfigLinePfsync(
|
|
Interface *iface, StateSyncClusterGroup *state_sync_group)
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
Configlet configlet(fw, "freebsd", "rc_conf_pfsync_interface");
|
|
configlet.removeComments();
|
|
configlet.collapseEmptyStrings(true);
|
|
configlet.setVariable("syncdev", iface->getName().c_str());
|
|
|
|
if (state_sync_group->getOptionsObject()->getBool("syncpeer"))
|
|
{
|
|
for (FWObjectTypedChildIterator it =
|
|
state_sync_group->findByType(FWObjectReference::TYPENAME);
|
|
it != it.end(); ++it)
|
|
{
|
|
Interface *cluster_iface = Interface::cast(
|
|
FWObjectReference::getObject(*it));
|
|
assert(cluster_iface);
|
|
|
|
if (cluster_iface->getId() == iface->getId()) continue;
|
|
|
|
IPv4 *ipv4 = IPv4::cast(cluster_iface->getFirstByType(IPv4::TYPENAME));
|
|
const InetAddr *addr = ipv4->getAddressPtr();
|
|
|
|
configlet.setVariable("have_syncpeer", 1);
|
|
configlet.setVariable("syncpeer", addr->toString().c_str());
|
|
}
|
|
}
|
|
interface_configuration_lines[iface->getName().c_str()] << configlet.expand();
|
|
|
|
} else
|
|
OSConfigurator_bsd::interfaceConfigLinePfsync(iface, state_sync_group);
|
|
}
|
|
|
|
QString OSConfigurator_freebsd::printAllInterfaceConfigurationLines()
|
|
{
|
|
FWOptions* options = fw->getOptionsObject();
|
|
if (options->getBool("generate_rc_conf_file"))
|
|
{
|
|
printIfconfigLines(ifconfig_lines);
|
|
printIfconfigLines(ipv6_ifconfig_lines);
|
|
|
|
if (!cloned_interfaces.isEmpty())
|
|
interface_configuration_lines["0_should_be_on_top_"] <<
|
|
QString("cloned_interfaces=\"%1\"")
|
|
.arg(cloned_interfaces.join(" "));
|
|
}
|
|
return OSConfigurator_bsd::printAllInterfaceConfigurationLines();
|
|
}
|
|
|
|
void OSConfigurator_freebsd::printIfconfigLines(const QMap<QString, QStringList>
|
|
&lines)
|
|
{
|
|
if (!lines.isEmpty())
|
|
{
|
|
QStringList keys = lines.keys();
|
|
keys.sort();
|
|
foreach (QString iface_name, keys)
|
|
{
|
|
const QStringList commands = lines[iface_name];
|
|
interface_configuration_lines[iface_name] <<
|
|
QString("ifconfig_%1=\"%2\"").arg(iface_name)
|
|
.arg(commands.join(" "));
|
|
}
|
|
}
|
|
}
|
|
|