mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-18 18:45:16 +00:00
bridge driver: extract platform specifics
* Move platform specific things (e.g. firewalling and route collision checks) into bridge_driver_platform * Create two platform specific implementations: - bridge_driver_linux: Linux implementation using iptables, it's actually the code moved from bridge_driver.c - bridge_driver_nop: dumb implementation that does nothing Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
6e69166ef1
commit
4ac708f250
@ -70,6 +70,7 @@ src/lxc/lxc_process.c
|
|||||||
src/libxl/libxl_driver.c
|
src/libxl/libxl_driver.c
|
||||||
src/libxl/libxl_conf.c
|
src/libxl/libxl_conf.c
|
||||||
src/network/bridge_driver.c
|
src/network/bridge_driver.c
|
||||||
|
src/network/bridge_driver_linux.c
|
||||||
src/node_device/node_device_driver.c
|
src/node_device/node_device_driver.c
|
||||||
src/node_device/node_device_hal.c
|
src/node_device/node_device_hal.c
|
||||||
src/node_device/node_device_linux_sysfs.c
|
src/node_device/node_device_linux_sysfs.c
|
||||||
|
@ -728,7 +728,11 @@ PARALLELS_DRIVER_SOURCES = \
|
|||||||
parallels/parallels_network.c
|
parallels/parallels_network.c
|
||||||
|
|
||||||
NETWORK_DRIVER_SOURCES = \
|
NETWORK_DRIVER_SOURCES = \
|
||||||
network/bridge_driver.h network/bridge_driver.c
|
network/bridge_driver.h network/bridge_driver.c \
|
||||||
|
network/bridge_driver_platform.h \
|
||||||
|
network/bridge_driver_platform.c \
|
||||||
|
$(NULL)
|
||||||
|
EXTRA_DIST += network/bridge_driver_linux.c network/bridge_driver_nop.c
|
||||||
|
|
||||||
INTERFACE_DRIVER_SOURCES =
|
INTERFACE_DRIVER_SOURCES =
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "virerror.h"
|
#include "virerror.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "bridge_driver.h"
|
#include "bridge_driver.h"
|
||||||
|
#include "bridge_driver_platform.h"
|
||||||
#include "network_conf.h"
|
#include "network_conf.h"
|
||||||
#include "device_conf.h"
|
#include "device_conf.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
@ -69,24 +70,6 @@
|
|||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_NETWORK
|
#define VIR_FROM_THIS VIR_FROM_NETWORK
|
||||||
|
|
||||||
/* Main driver state */
|
|
||||||
struct _virNetworkDriverState {
|
|
||||||
virMutex lock;
|
|
||||||
|
|
||||||
virNetworkObjList networks;
|
|
||||||
|
|
||||||
char *networkConfigDir;
|
|
||||||
char *networkAutostartDir;
|
|
||||||
char *stateDir;
|
|
||||||
char *pidDir;
|
|
||||||
char *dnsmasqStateDir;
|
|
||||||
char *radvdStateDir;
|
|
||||||
dnsmasqCapsPtr dnsmasqCaps;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _virNetworkDriverState virNetworkDriverState;
|
|
||||||
typedef virNetworkDriverState *virNetworkDriverStatePtr;
|
|
||||||
|
|
||||||
static void networkDriverLock(virNetworkDriverStatePtr driver)
|
static void networkDriverLock(virNetworkDriverStatePtr driver)
|
||||||
{
|
{
|
||||||
virMutexLock(&driver->lock);
|
virMutexLock(&driver->lock);
|
||||||
@ -1522,597 +1505,6 @@ networkRefreshDaemons(virNetworkDriverStatePtr driver)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
|
|
||||||
virNetworkIpDefPtr ipdef)
|
|
||||||
{
|
|
||||||
int prefix = virNetworkIpDefPrefix(ipdef);
|
|
||||||
const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
|
|
||||||
|
|
||||||
if (prefix < 0) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Invalid prefix or netmask for '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto masqerr1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow forwarding packets from the bridge interface */
|
|
||||||
if (iptablesAddForwardAllowOut(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow forwarding from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto masqerr1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow forwarding packets to the bridge interface if they are
|
|
||||||
* part of an existing connection
|
|
||||||
*/
|
|
||||||
if (iptablesAddForwardAllowRelatedIn(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow forwarding to '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto masqerr2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable masquerading.
|
|
||||||
*
|
|
||||||
* We need to end up with 3 rules in the table in this order
|
|
||||||
*
|
|
||||||
* 1. protocol=tcp with sport mapping restriction
|
|
||||||
* 2. protocol=udp with sport mapping restriction
|
|
||||||
* 3. generic any protocol
|
|
||||||
*
|
|
||||||
* The sport mappings are required, because default IPtables
|
|
||||||
* MASQUERADE maintain port numbers unchanged where possible.
|
|
||||||
*
|
|
||||||
* NFS can be configured to only "trust" port numbers < 1023.
|
|
||||||
*
|
|
||||||
* Guests using NAT thus need to be prevented from having port
|
|
||||||
* numbers < 1023, otherwise they can bypass the NFS "security"
|
|
||||||
* check on the source port number.
|
|
||||||
*
|
|
||||||
* Since we use '--insert' to add rules to the header of the
|
|
||||||
* chain, we actually need to add them in the reverse of the
|
|
||||||
* order just mentioned !
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* First the generic masquerade rule for other protocols */
|
|
||||||
if (iptablesAddForwardMasquerade(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
forwardIf,
|
|
||||||
&network->def->forward.addr,
|
|
||||||
&network->def->forward.port,
|
|
||||||
NULL) < 0) {
|
|
||||||
if (forwardIf)
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to enable masquerading to %s"),
|
|
||||||
forwardIf);
|
|
||||||
else
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
|
|
||||||
_("failed to add iptables rule to enable masquerading"));
|
|
||||||
goto masqerr3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UDP with a source port restriction */
|
|
||||||
if (iptablesAddForwardMasquerade(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
forwardIf,
|
|
||||||
&network->def->forward.addr,
|
|
||||||
&network->def->forward.port,
|
|
||||||
"udp") < 0) {
|
|
||||||
if (forwardIf)
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to enable UDP masquerading to %s"),
|
|
||||||
forwardIf);
|
|
||||||
else
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
|
|
||||||
_("failed to add iptables rule to enable UDP masquerading"));
|
|
||||||
goto masqerr4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TCP with a source port restriction */
|
|
||||||
if (iptablesAddForwardMasquerade(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
forwardIf,
|
|
||||||
&network->def->forward.addr,
|
|
||||||
&network->def->forward.port,
|
|
||||||
"tcp") < 0) {
|
|
||||||
if (forwardIf)
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to enable TCP masquerading to %s"),
|
|
||||||
forwardIf);
|
|
||||||
else
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
|
|
||||||
_("failed to add iptables rule to enable TCP masquerading"));
|
|
||||||
goto masqerr5;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
masqerr5:
|
|
||||||
iptablesRemoveForwardMasquerade(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
forwardIf,
|
|
||||||
&network->def->forward.addr,
|
|
||||||
&network->def->forward.port,
|
|
||||||
"udp");
|
|
||||||
masqerr4:
|
|
||||||
iptablesRemoveForwardMasquerade(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
forwardIf,
|
|
||||||
&network->def->forward.addr,
|
|
||||||
&network->def->forward.port,
|
|
||||||
NULL);
|
|
||||||
masqerr3:
|
|
||||||
iptablesRemoveForwardAllowRelatedIn(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf);
|
|
||||||
masqerr2:
|
|
||||||
iptablesRemoveForwardAllowOut(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf);
|
|
||||||
masqerr1:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network,
|
|
||||||
virNetworkIpDefPtr ipdef)
|
|
||||||
{
|
|
||||||
int prefix = virNetworkIpDefPrefix(ipdef);
|
|
||||||
const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
|
|
||||||
|
|
||||||
if (prefix >= 0) {
|
|
||||||
iptablesRemoveForwardMasquerade(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
forwardIf,
|
|
||||||
&network->def->forward.addr,
|
|
||||||
&network->def->forward.port,
|
|
||||||
"tcp");
|
|
||||||
iptablesRemoveForwardMasquerade(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
forwardIf,
|
|
||||||
&network->def->forward.addr,
|
|
||||||
&network->def->forward.port,
|
|
||||||
"udp");
|
|
||||||
iptablesRemoveForwardMasquerade(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
forwardIf,
|
|
||||||
&network->def->forward.addr,
|
|
||||||
&network->def->forward.port,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
iptablesRemoveForwardAllowRelatedIn(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf);
|
|
||||||
iptablesRemoveForwardAllowOut(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
networkAddRoutingFirewallRules(virNetworkObjPtr network,
|
|
||||||
virNetworkIpDefPtr ipdef)
|
|
||||||
{
|
|
||||||
int prefix = virNetworkIpDefPrefix(ipdef);
|
|
||||||
const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
|
|
||||||
|
|
||||||
if (prefix < 0) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Invalid prefix or netmask for '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto routeerr1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow routing packets from the bridge interface */
|
|
||||||
if (iptablesAddForwardAllowOut(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow routing from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto routeerr1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow routing packets to the bridge interface */
|
|
||||||
if (iptablesAddForwardAllowIn(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow routing to '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto routeerr2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
routeerr2:
|
|
||||||
iptablesRemoveForwardAllowOut(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf);
|
|
||||||
routeerr1:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
networkRemoveRoutingFirewallRules(virNetworkObjPtr network,
|
|
||||||
virNetworkIpDefPtr ipdef)
|
|
||||||
{
|
|
||||||
int prefix = virNetworkIpDefPrefix(ipdef);
|
|
||||||
const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
|
|
||||||
|
|
||||||
if (prefix >= 0) {
|
|
||||||
iptablesRemoveForwardAllowIn(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf);
|
|
||||||
|
|
||||||
iptablesRemoveForwardAllowOut(&ipdef->address,
|
|
||||||
prefix,
|
|
||||||
network->def->bridge,
|
|
||||||
forwardIf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add all once/network rules required for IPv6.
|
|
||||||
* If no IPv6 addresses are defined and <network ipv6='yes'> is
|
|
||||||
* specified, then allow IPv6 commuinications between virtual systems.
|
|
||||||
* If any IPv6 addresses are defined, then add the rules for regular operation.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
networkAddGeneralIp6tablesRules(virNetworkObjPtr network)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) &&
|
|
||||||
!network->def->ipv6nogw) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Catch all rules to block forwarding to/from bridges */
|
|
||||||
|
|
||||||
if (iptablesAddForwardRejectOut(AF_INET6, network->def->bridge) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add ip6tables rule to block outbound traffic from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iptablesAddForwardRejectIn(AF_INET6, network->def->bridge) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add ip6tables rule to block inbound traffic to '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allow traffic between guests on the same bridge */
|
|
||||||
if (iptablesAddForwardAllowCross(AF_INET6, network->def->bridge) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add ip6tables rule to allow cross bridge traffic on '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if no IPv6 addresses are defined, we are done. */
|
|
||||||
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* allow DNS over IPv6 */
|
|
||||||
if (iptablesAddTcpInput(AF_INET6, network->def->bridge, 53) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add ip6tables rule to allow DNS requests from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 53) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add ip6tables rule to allow DNS requests from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 547) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add ip6tables rule to allow DHCP6 requests from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err6;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* unwind in reverse order from the point of failure */
|
|
||||||
err6:
|
|
||||||
iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53);
|
|
||||||
err5:
|
|
||||||
iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53);
|
|
||||||
err4:
|
|
||||||
iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge);
|
|
||||||
err3:
|
|
||||||
iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge);
|
|
||||||
err2:
|
|
||||||
iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge);
|
|
||||||
err1:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
networkRemoveGeneralIp6tablesRules(virNetworkObjPtr network)
|
|
||||||
{
|
|
||||||
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) &&
|
|
||||||
!network->def->ipv6nogw) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) {
|
|
||||||
iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 547);
|
|
||||||
iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53);
|
|
||||||
iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the following rules are there if no IPv6 address has been defined
|
|
||||||
* but network->def->ipv6nogw == true
|
|
||||||
*/
|
|
||||||
iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge);
|
|
||||||
iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge);
|
|
||||||
iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
networkAddGeneralFirewallRules(virNetworkObjPtr network)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
virNetworkIpDefPtr ipv4def;
|
|
||||||
|
|
||||||
/* First look for first IPv4 address that has dhcp or tftpboot defined. */
|
|
||||||
/* We support dhcp config on 1 IPv4 interface only. */
|
|
||||||
for (i = 0;
|
|
||||||
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
|
|
||||||
i++) {
|
|
||||||
if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow DHCP requests through to dnsmasq */
|
|
||||||
|
|
||||||
if (iptablesAddTcpInput(AF_INET, network->def->bridge, 67) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iptablesAddUdpInput(AF_INET, network->def->bridge, 67) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we are doing local DHCP service on this network, attempt to
|
|
||||||
* add a rule that will fixup the checksum of DHCP response
|
|
||||||
* packets back to the guests (but report failure without
|
|
||||||
* aborting, since not all iptables implementations support it).
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (ipv4def && (ipv4def->nranges || ipv4def->nhosts) &&
|
|
||||||
(iptablesAddOutputFixUdpChecksum(network->def->bridge, 68) < 0)) {
|
|
||||||
VIR_WARN("Could not add rule to fixup DHCP response checksums "
|
|
||||||
"on network '%s'.", network->def->name);
|
|
||||||
VIR_WARN("May need to update iptables package & kernel to support CHECKSUM rule.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow DNS requests through to dnsmasq */
|
|
||||||
if (iptablesAddTcpInput(AF_INET, network->def->bridge, 53) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow DNS requests from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iptablesAddUdpInput(AF_INET, network->def->bridge, 53) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow DNS requests from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow TFTP requests through to dnsmasq if necessary */
|
|
||||||
if (ipv4def && ipv4def->tftproot &&
|
|
||||||
iptablesAddUdpInput(AF_INET, network->def->bridge, 69) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow TFTP requests from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Catch all rules to block forwarding to/from bridges */
|
|
||||||
|
|
||||||
if (iptablesAddForwardRejectOut(AF_INET, network->def->bridge) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to block outbound traffic from '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iptablesAddForwardRejectIn(AF_INET, network->def->bridge) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to block inbound traffic to '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err7;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allow traffic between guests on the same bridge */
|
|
||||||
if (iptablesAddForwardAllowCross(AF_INET, network->def->bridge) < 0) {
|
|
||||||
virReportError(VIR_ERR_SYSTEM_ERROR,
|
|
||||||
_("failed to add iptables rule to allow cross bridge traffic on '%s'"),
|
|
||||||
network->def->bridge);
|
|
||||||
goto err8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add IPv6 general rules, if needed */
|
|
||||||
if (networkAddGeneralIp6tablesRules(network) < 0) {
|
|
||||||
goto err9;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* unwind in reverse order from the point of failure */
|
|
||||||
err9:
|
|
||||||
iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
|
|
||||||
err8:
|
|
||||||
iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
|
|
||||||
err7:
|
|
||||||
iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
|
|
||||||
err6:
|
|
||||||
if (ipv4def && ipv4def->tftproot) {
|
|
||||||
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
|
|
||||||
}
|
|
||||||
err5:
|
|
||||||
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
|
|
||||||
err4:
|
|
||||||
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
|
|
||||||
err3:
|
|
||||||
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
|
|
||||||
err2:
|
|
||||||
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67);
|
|
||||||
err1:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
networkRemoveGeneralFirewallRules(virNetworkObjPtr network)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
virNetworkIpDefPtr ipv4def;
|
|
||||||
|
|
||||||
networkRemoveGeneralIp6tablesRules(network);
|
|
||||||
|
|
||||||
for (i = 0;
|
|
||||||
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
|
|
||||||
i++) {
|
|
||||||
if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
|
|
||||||
iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
|
|
||||||
iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
|
|
||||||
if (ipv4def && ipv4def->tftproot) {
|
|
||||||
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
|
|
||||||
}
|
|
||||||
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
|
|
||||||
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
|
|
||||||
if (ipv4def && (ipv4def->nranges || ipv4def->nhosts)) {
|
|
||||||
iptablesRemoveOutputFixUdpChecksum(network->def->bridge, 68);
|
|
||||||
}
|
|
||||||
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
|
|
||||||
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
networkAddIpSpecificFirewallRules(virNetworkObjPtr network,
|
|
||||||
virNetworkIpDefPtr ipdef)
|
|
||||||
{
|
|
||||||
/* NB: in the case of IPv6, routing rules are added when the
|
|
||||||
* forward mode is NAT. This is because IPv6 has no NAT.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) {
|
|
||||||
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
|
|
||||||
return networkAddMasqueradingFirewallRules(network, ipdef);
|
|
||||||
else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
|
|
||||||
return networkAddRoutingFirewallRules(network, ipdef);
|
|
||||||
} else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
|
|
||||||
return networkAddRoutingFirewallRules(network, ipdef);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network,
|
|
||||||
virNetworkIpDefPtr ipdef)
|
|
||||||
{
|
|
||||||
if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) {
|
|
||||||
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
|
|
||||||
networkRemoveMasqueradingFirewallRules(network, ipdef);
|
|
||||||
else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
|
|
||||||
networkRemoveRoutingFirewallRules(network, ipdef);
|
|
||||||
} else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
|
|
||||||
networkRemoveRoutingFirewallRules(network, ipdef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add all rules for all ip addresses (and general rules) on a network */
|
|
||||||
static int
|
|
||||||
networkAddFirewallRules(virNetworkObjPtr network)
|
|
||||||
{
|
|
||||||
size_t i, j;
|
|
||||||
virNetworkIpDefPtr ipdef;
|
|
||||||
virErrorPtr orig_error;
|
|
||||||
|
|
||||||
/* Add "once per network" rules */
|
|
||||||
if (networkAddGeneralFirewallRules(network) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (i = 0;
|
|
||||||
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i));
|
|
||||||
i++) {
|
|
||||||
/* Add address-specific iptables rules */
|
|
||||||
if (networkAddIpSpecificFirewallRules(network, ipdef) < 0) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err:
|
|
||||||
/* store the previous error message before attempting removal of rules */
|
|
||||||
orig_error = virSaveLastError();
|
|
||||||
|
|
||||||
/* The final failed call to networkAddIpSpecificFirewallRules will
|
|
||||||
* have removed any rules it created, but we need to remove those
|
|
||||||
* added for previous IP addresses.
|
|
||||||
*/
|
|
||||||
for (j = 0; j < i; j++) {
|
|
||||||
if ((ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, j)))
|
|
||||||
networkRemoveIpSpecificFirewallRules(network, ipdef);
|
|
||||||
}
|
|
||||||
networkRemoveGeneralFirewallRules(network);
|
|
||||||
|
|
||||||
/* return the original error */
|
|
||||||
virSetError(orig_error);
|
|
||||||
virFreeError(orig_error);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove all rules for all ip addresses (and general rules) on a network */
|
|
||||||
static void
|
|
||||||
networkRemoveFirewallRules(virNetworkObjPtr network)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
virNetworkIpDefPtr ipdef;
|
|
||||||
|
|
||||||
for (i = 0;
|
|
||||||
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i));
|
|
||||||
i++) {
|
|
||||||
networkRemoveIpSpecificFirewallRules(network, ipdef);
|
|
||||||
}
|
|
||||||
networkRemoveGeneralFirewallRules(network);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
networkReloadFirewallRules(virNetworkDriverStatePtr driver)
|
networkReloadFirewallRules(virNetworkDriverStatePtr driver)
|
||||||
{
|
{
|
||||||
@ -2221,104 +1613,6 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PROC_NET_ROUTE "/proc/net/route"
|
|
||||||
|
|
||||||
/* XXX: This function can be a lot more exhaustive, there are certainly
|
|
||||||
* other scenarios where we can ruin host network connectivity.
|
|
||||||
* XXX: Using a proper library is preferred over parsing /proc
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
networkCheckRouteCollision(virNetworkObjPtr network)
|
|
||||||
{
|
|
||||||
int ret = 0, len;
|
|
||||||
char *cur, *buf = NULL;
|
|
||||||
/* allow for up to 100000 routes (each line is 128 bytes) */
|
|
||||||
enum {MAX_ROUTE_SIZE = 128*100000};
|
|
||||||
|
|
||||||
/* Read whole routing table into memory */
|
|
||||||
if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Dropping the last character shouldn't hurt */
|
|
||||||
if (len > 0)
|
|
||||||
buf[len-1] = '\0';
|
|
||||||
|
|
||||||
VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
|
|
||||||
|
|
||||||
if (!STRPREFIX(buf, "Iface"))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* First line is just headings, skip it */
|
|
||||||
cur = strchr(buf, '\n');
|
|
||||||
if (cur)
|
|
||||||
cur++;
|
|
||||||
|
|
||||||
while (cur) {
|
|
||||||
char iface[17], dest[128], mask[128];
|
|
||||||
unsigned int addr_val, mask_val;
|
|
||||||
virNetworkIpDefPtr ipdef;
|
|
||||||
int num;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
|
|
||||||
char *nl = strchr(cur, '\n');
|
|
||||||
if (nl) {
|
|
||||||
*nl++ = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
|
|
||||||
iface, dest, mask);
|
|
||||||
cur = nl;
|
|
||||||
|
|
||||||
if (num != 3) {
|
|
||||||
VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
|
|
||||||
VIR_DEBUG("Failed to convert network address %s to uint", dest);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
|
|
||||||
VIR_DEBUG("Failed to convert network mask %s to uint", mask);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_val &= mask_val;
|
|
||||||
|
|
||||||
for (i = 0;
|
|
||||||
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
|
|
||||||
i++) {
|
|
||||||
|
|
||||||
unsigned int net_dest;
|
|
||||||
virSocketAddr netmask;
|
|
||||||
|
|
||||||
if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
|
|
||||||
VIR_WARN("Failed to get netmask of '%s'",
|
|
||||||
network->def->bridge);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
|
|
||||||
netmask.data.inet4.sin_addr.s_addr);
|
|
||||||
|
|
||||||
if ((net_dest == addr_val) &&
|
|
||||||
(netmask.data.inet4.sin_addr.s_addr == mask_val)) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Network is already in use by interface %s"),
|
|
||||||
iface);
|
|
||||||
ret = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
VIR_FREE(buf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add an IP address to a bridge */
|
/* add an IP address to a bridge */
|
||||||
static int
|
static int
|
||||||
networkAddAddrToBridge(virNetworkObjPtr network,
|
networkAddAddrToBridge(virNetworkObjPtr network,
|
||||||
|
709
src/network/bridge_driver_linux.c
Normal file
709
src/network/bridge_driver_linux.c
Normal file
@ -0,0 +1,709 @@
|
|||||||
|
/*
|
||||||
|
* bridge_driver_linux.c: Linux implementation of bridge driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2013 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2006 Daniel P. Berrange
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "virfile.h"
|
||||||
|
#include "viriptables.h"
|
||||||
|
#include "virstring.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
||||||
|
|
||||||
|
#define PROC_NET_ROUTE "/proc/net/route"
|
||||||
|
|
||||||
|
/* XXX: This function can be a lot more exhaustive, there are certainly
|
||||||
|
* other scenarios where we can ruin host network connectivity.
|
||||||
|
* XXX: Using a proper library is preferred over parsing /proc
|
||||||
|
*/
|
||||||
|
int networkCheckRouteCollision(virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
int ret = 0, len;
|
||||||
|
char *cur, *buf = NULL;
|
||||||
|
/* allow for up to 100000 routes (each line is 128 bytes) */
|
||||||
|
enum {MAX_ROUTE_SIZE = 128*100000};
|
||||||
|
|
||||||
|
/* Read whole routing table into memory */
|
||||||
|
if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Dropping the last character shouldn't hurt */
|
||||||
|
if (len > 0)
|
||||||
|
buf[len-1] = '\0';
|
||||||
|
|
||||||
|
VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
|
||||||
|
|
||||||
|
if (!STRPREFIX(buf, "Iface"))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* First line is just headings, skip it */
|
||||||
|
cur = strchr(buf, '\n');
|
||||||
|
if (cur)
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
while (cur) {
|
||||||
|
char iface[17], dest[128], mask[128];
|
||||||
|
unsigned int addr_val, mask_val;
|
||||||
|
virNetworkIpDefPtr ipdef;
|
||||||
|
int num;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
|
||||||
|
char *nl = strchr(cur, '\n');
|
||||||
|
if (nl) {
|
||||||
|
*nl++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
|
||||||
|
iface, dest, mask);
|
||||||
|
cur = nl;
|
||||||
|
|
||||||
|
if (num != 3) {
|
||||||
|
VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
|
||||||
|
VIR_DEBUG("Failed to convert network address %s to uint", dest);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
|
||||||
|
VIR_DEBUG("Failed to convert network mask %s to uint", mask);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_val &= mask_val;
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
|
||||||
|
i++) {
|
||||||
|
|
||||||
|
unsigned int net_dest;
|
||||||
|
virSocketAddr netmask;
|
||||||
|
|
||||||
|
if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
|
||||||
|
VIR_WARN("Failed to get netmask of '%s'",
|
||||||
|
network->def->bridge);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
|
||||||
|
netmask.data.inet4.sin_addr.s_addr);
|
||||||
|
|
||||||
|
if ((net_dest == addr_val) &&
|
||||||
|
(netmask.data.inet4.sin_addr.s_addr == mask_val)) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Network is already in use by interface %s"),
|
||||||
|
iface);
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
VIR_FREE(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
|
||||||
|
|
||||||
|
if (prefix < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Invalid prefix or netmask for '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto masqerr1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow forwarding packets from the bridge interface */
|
||||||
|
if (iptablesAddForwardAllowOut(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow forwarding from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto masqerr1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow forwarding packets to the bridge interface if they are
|
||||||
|
* part of an existing connection
|
||||||
|
*/
|
||||||
|
if (iptablesAddForwardAllowRelatedIn(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow forwarding to '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto masqerr2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable masquerading.
|
||||||
|
*
|
||||||
|
* We need to end up with 3 rules in the table in this order
|
||||||
|
*
|
||||||
|
* 1. protocol=tcp with sport mapping restriction
|
||||||
|
* 2. protocol=udp with sport mapping restriction
|
||||||
|
* 3. generic any protocol
|
||||||
|
*
|
||||||
|
* The sport mappings are required, because default IPtables
|
||||||
|
* MASQUERADE maintain port numbers unchanged where possible.
|
||||||
|
*
|
||||||
|
* NFS can be configured to only "trust" port numbers < 1023.
|
||||||
|
*
|
||||||
|
* Guests using NAT thus need to be prevented from having port
|
||||||
|
* numbers < 1023, otherwise they can bypass the NFS "security"
|
||||||
|
* check on the source port number.
|
||||||
|
*
|
||||||
|
* Since we use '--insert' to add rules to the header of the
|
||||||
|
* chain, we actually need to add them in the reverse of the
|
||||||
|
* order just mentioned !
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* First the generic masquerade rule for other protocols */
|
||||||
|
if (iptablesAddForwardMasquerade(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
forwardIf,
|
||||||
|
&network->def->forward.addr,
|
||||||
|
&network->def->forward.port,
|
||||||
|
NULL) < 0) {
|
||||||
|
if (forwardIf)
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to enable masquerading to %s"),
|
||||||
|
forwardIf);
|
||||||
|
else
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
|
||||||
|
_("failed to add iptables rule to enable masquerading"));
|
||||||
|
goto masqerr3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UDP with a source port restriction */
|
||||||
|
if (iptablesAddForwardMasquerade(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
forwardIf,
|
||||||
|
&network->def->forward.addr,
|
||||||
|
&network->def->forward.port,
|
||||||
|
"udp") < 0) {
|
||||||
|
if (forwardIf)
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to enable UDP masquerading to %s"),
|
||||||
|
forwardIf);
|
||||||
|
else
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
|
||||||
|
_("failed to add iptables rule to enable UDP masquerading"));
|
||||||
|
goto masqerr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TCP with a source port restriction */
|
||||||
|
if (iptablesAddForwardMasquerade(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
forwardIf,
|
||||||
|
&network->def->forward.addr,
|
||||||
|
&network->def->forward.port,
|
||||||
|
"tcp") < 0) {
|
||||||
|
if (forwardIf)
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to enable TCP masquerading to %s"),
|
||||||
|
forwardIf);
|
||||||
|
else
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
|
||||||
|
_("failed to add iptables rule to enable TCP masquerading"));
|
||||||
|
goto masqerr5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
masqerr5:
|
||||||
|
iptablesRemoveForwardMasquerade(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
forwardIf,
|
||||||
|
&network->def->forward.addr,
|
||||||
|
&network->def->forward.port,
|
||||||
|
"udp");
|
||||||
|
masqerr4:
|
||||||
|
iptablesRemoveForwardMasquerade(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
forwardIf,
|
||||||
|
&network->def->forward.addr,
|
||||||
|
&network->def->forward.port,
|
||||||
|
NULL);
|
||||||
|
masqerr3:
|
||||||
|
iptablesRemoveForwardAllowRelatedIn(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf);
|
||||||
|
masqerr2:
|
||||||
|
iptablesRemoveForwardAllowOut(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf);
|
||||||
|
masqerr1:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
|
||||||
|
|
||||||
|
if (prefix >= 0) {
|
||||||
|
iptablesRemoveForwardMasquerade(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
forwardIf,
|
||||||
|
&network->def->forward.addr,
|
||||||
|
&network->def->forward.port,
|
||||||
|
"tcp");
|
||||||
|
iptablesRemoveForwardMasquerade(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
forwardIf,
|
||||||
|
&network->def->forward.addr,
|
||||||
|
&network->def->forward.port,
|
||||||
|
"udp");
|
||||||
|
iptablesRemoveForwardMasquerade(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
forwardIf,
|
||||||
|
&network->def->forward.addr,
|
||||||
|
&network->def->forward.port,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
iptablesRemoveForwardAllowRelatedIn(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf);
|
||||||
|
iptablesRemoveForwardAllowOut(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddRoutingFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
|
||||||
|
|
||||||
|
if (prefix < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Invalid prefix or netmask for '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto routeerr1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow routing packets from the bridge interface */
|
||||||
|
if (iptablesAddForwardAllowOut(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow routing from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto routeerr1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow routing packets to the bridge interface */
|
||||||
|
if (iptablesAddForwardAllowIn(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow routing to '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto routeerr2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
routeerr2:
|
||||||
|
iptablesRemoveForwardAllowOut(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf);
|
||||||
|
routeerr1:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveRoutingFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
|
||||||
|
|
||||||
|
if (prefix >= 0) {
|
||||||
|
iptablesRemoveForwardAllowIn(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf);
|
||||||
|
|
||||||
|
iptablesRemoveForwardAllowOut(&ipdef->address,
|
||||||
|
prefix,
|
||||||
|
network->def->bridge,
|
||||||
|
forwardIf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add all once/network rules required for IPv6.
|
||||||
|
* If no IPv6 addresses are defined and <network ipv6='yes'> is
|
||||||
|
* specified, then allow IPv6 commuinications between virtual systems.
|
||||||
|
* If any IPv6 addresses are defined, then add the rules for regular operation.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
networkAddGeneralIp6tablesRules(virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) &&
|
||||||
|
!network->def->ipv6nogw) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Catch all rules to block forwarding to/from bridges */
|
||||||
|
|
||||||
|
if (iptablesAddForwardRejectOut(AF_INET6, network->def->bridge) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add ip6tables rule to block outbound traffic from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iptablesAddForwardRejectIn(AF_INET6, network->def->bridge) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add ip6tables rule to block inbound traffic to '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow traffic between guests on the same bridge */
|
||||||
|
if (iptablesAddForwardAllowCross(AF_INET6, network->def->bridge) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add ip6tables rule to allow cross bridge traffic on '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if no IPv6 addresses are defined, we are done. */
|
||||||
|
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* allow DNS over IPv6 */
|
||||||
|
if (iptablesAddTcpInput(AF_INET6, network->def->bridge, 53) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add ip6tables rule to allow DNS requests from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 53) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add ip6tables rule to allow DNS requests from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 547) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add ip6tables rule to allow DHCP6 requests from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* unwind in reverse order from the point of failure */
|
||||||
|
err6:
|
||||||
|
iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53);
|
||||||
|
err5:
|
||||||
|
iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53);
|
||||||
|
err4:
|
||||||
|
iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge);
|
||||||
|
err3:
|
||||||
|
iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge);
|
||||||
|
err2:
|
||||||
|
iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge);
|
||||||
|
err1:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
networkRemoveGeneralIp6tablesRules(virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) &&
|
||||||
|
!network->def->ipv6nogw) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) {
|
||||||
|
iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 547);
|
||||||
|
iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53);
|
||||||
|
iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the following rules are there if no IPv6 address has been defined
|
||||||
|
* but network->def->ipv6nogw == true
|
||||||
|
*/
|
||||||
|
iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge);
|
||||||
|
iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge);
|
||||||
|
iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddGeneralFirewallRules(virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
virNetworkIpDefPtr ipv4def;
|
||||||
|
|
||||||
|
/* First look for first IPv4 address that has dhcp or tftpboot defined. */
|
||||||
|
/* We support dhcp config on 1 IPv4 interface only. */
|
||||||
|
for (i = 0;
|
||||||
|
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
|
||||||
|
i++) {
|
||||||
|
if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow DHCP requests through to dnsmasq */
|
||||||
|
|
||||||
|
if (iptablesAddTcpInput(AF_INET, network->def->bridge, 67) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iptablesAddUdpInput(AF_INET, network->def->bridge, 67) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are doing local DHCP service on this network, attempt to
|
||||||
|
* add a rule that will fixup the checksum of DHCP response
|
||||||
|
* packets back to the guests (but report failure without
|
||||||
|
* aborting, since not all iptables implementations support it).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ipv4def && (ipv4def->nranges || ipv4def->nhosts) &&
|
||||||
|
(iptablesAddOutputFixUdpChecksum(network->def->bridge, 68) < 0)) {
|
||||||
|
VIR_WARN("Could not add rule to fixup DHCP response checksums "
|
||||||
|
"on network '%s'.", network->def->name);
|
||||||
|
VIR_WARN("May need to update iptables package & kernel to support CHECKSUM rule.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow DNS requests through to dnsmasq */
|
||||||
|
if (iptablesAddTcpInput(AF_INET, network->def->bridge, 53) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow DNS requests from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iptablesAddUdpInput(AF_INET, network->def->bridge, 53) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow DNS requests from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow TFTP requests through to dnsmasq if necessary */
|
||||||
|
if (ipv4def && ipv4def->tftproot &&
|
||||||
|
iptablesAddUdpInput(AF_INET, network->def->bridge, 69) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow TFTP requests from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Catch all rules to block forwarding to/from bridges */
|
||||||
|
|
||||||
|
if (iptablesAddForwardRejectOut(AF_INET, network->def->bridge) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to block outbound traffic from '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iptablesAddForwardRejectIn(AF_INET, network->def->bridge) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to block inbound traffic to '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow traffic between guests on the same bridge */
|
||||||
|
if (iptablesAddForwardAllowCross(AF_INET, network->def->bridge) < 0) {
|
||||||
|
virReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
|
_("failed to add iptables rule to allow cross bridge traffic on '%s'"),
|
||||||
|
network->def->bridge);
|
||||||
|
goto err8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add IPv6 general rules, if needed */
|
||||||
|
if (networkAddGeneralIp6tablesRules(network) < 0) {
|
||||||
|
goto err9;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* unwind in reverse order from the point of failure */
|
||||||
|
err9:
|
||||||
|
iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
|
||||||
|
err8:
|
||||||
|
iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
|
||||||
|
err7:
|
||||||
|
iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
|
||||||
|
err6:
|
||||||
|
if (ipv4def && ipv4def->tftproot) {
|
||||||
|
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
|
||||||
|
}
|
||||||
|
err5:
|
||||||
|
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
|
||||||
|
err4:
|
||||||
|
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
|
||||||
|
err3:
|
||||||
|
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
|
||||||
|
err2:
|
||||||
|
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67);
|
||||||
|
err1:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveGeneralFirewallRules(virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
virNetworkIpDefPtr ipv4def;
|
||||||
|
|
||||||
|
networkRemoveGeneralIp6tablesRules(network);
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
|
||||||
|
i++) {
|
||||||
|
if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
|
||||||
|
iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
|
||||||
|
iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
|
||||||
|
if (ipv4def && ipv4def->tftproot) {
|
||||||
|
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
|
||||||
|
}
|
||||||
|
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
|
||||||
|
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
|
||||||
|
if (ipv4def && (ipv4def->nranges || ipv4def->nhosts)) {
|
||||||
|
iptablesRemoveOutputFixUdpChecksum(network->def->bridge, 68);
|
||||||
|
}
|
||||||
|
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
|
||||||
|
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67);
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddIpSpecificFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
/* NB: in the case of IPv6, routing rules are added when the
|
||||||
|
* forward mode is NAT. This is because IPv6 has no NAT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) {
|
||||||
|
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
|
||||||
|
return networkAddMasqueradingFirewallRules(network, ipdef);
|
||||||
|
else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
|
||||||
|
return networkAddRoutingFirewallRules(network, ipdef);
|
||||||
|
} else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
|
||||||
|
return networkAddRoutingFirewallRules(network, ipdef);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) {
|
||||||
|
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
|
||||||
|
networkRemoveMasqueradingFirewallRules(network, ipdef);
|
||||||
|
else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
|
||||||
|
networkRemoveRoutingFirewallRules(network, ipdef);
|
||||||
|
} else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
|
||||||
|
networkRemoveRoutingFirewallRules(network, ipdef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add all rules for all ip addresses (and general rules) on a network */
|
||||||
|
int networkAddFirewallRules(virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
size_t i, j;
|
||||||
|
virNetworkIpDefPtr ipdef;
|
||||||
|
virErrorPtr orig_error;
|
||||||
|
|
||||||
|
/* Add "once per network" rules */
|
||||||
|
if (networkAddGeneralFirewallRules(network) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i));
|
||||||
|
i++) {
|
||||||
|
/* Add address-specific iptables rules */
|
||||||
|
if (networkAddIpSpecificFirewallRules(network, ipdef) < 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* store the previous error message before attempting removal of rules */
|
||||||
|
orig_error = virSaveLastError();
|
||||||
|
|
||||||
|
/* The final failed call to networkAddIpSpecificFirewallRules will
|
||||||
|
* have removed any rules it created, but we need to remove those
|
||||||
|
* added for previous IP addresses.
|
||||||
|
*/
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
if ((ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, j)))
|
||||||
|
networkRemoveIpSpecificFirewallRules(network, ipdef);
|
||||||
|
}
|
||||||
|
networkRemoveGeneralFirewallRules(network);
|
||||||
|
|
||||||
|
/* return the original error */
|
||||||
|
virSetError(orig_error);
|
||||||
|
virFreeError(orig_error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove all rules for all ip addresses (and general rules) on a network */
|
||||||
|
void networkRemoveFirewallRules(virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
virNetworkIpDefPtr ipdef;
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i));
|
||||||
|
i++) {
|
||||||
|
networkRemoveIpSpecificFirewallRules(network, ipdef);
|
||||||
|
}
|
||||||
|
networkRemoveGeneralFirewallRules(network);
|
||||||
|
}
|
78
src/network/bridge_driver_nop.c
Normal file
78
src/network/bridge_driver_nop.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006-2013 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2006 Daniel P. Berrange
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
int networkCheckRouteCollision(virNetworkObjPtr network)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddMasqueradingFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
|
||||||
|
virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
|
||||||
|
virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddRoutingFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
|
||||||
|
virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveRoutingFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
|
||||||
|
virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddGeneralFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveGeneralFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddIpSpecificFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
|
||||||
|
virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
|
||||||
|
virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int networkAddFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void networkRemoveFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
}
|
32
src/network/bridge_driver_platform.c
Normal file
32
src/network/bridge_driver_platform.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* bridge_driver_platform.c: platform specific part of bridge driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2013 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2006 Daniel P. Berrange
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "bridge_driver_platform.h"
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
# include "bridge_driver_linux.c"
|
||||||
|
#else
|
||||||
|
# include "bridge_driver_nop.c"
|
||||||
|
#endif
|
79
src/network/bridge_driver_platform.h
Normal file
79
src/network/bridge_driver_platform.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* bridge_driver.h: platform specific routines for bridge driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2013 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2006 Daniel P. Berrange
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VIR_BRIDGE_DRIVER_PLATFORM_H__
|
||||||
|
# define __VIR_BRIDGE_DRIVER_PLATFORM_H__
|
||||||
|
|
||||||
|
# include "internal.h"
|
||||||
|
# include "virlog.h"
|
||||||
|
# include "virthread.h"
|
||||||
|
# include "virdnsmasq.h"
|
||||||
|
# include "network_conf.h"
|
||||||
|
|
||||||
|
/* Main driver state */
|
||||||
|
struct _virNetworkDriverState {
|
||||||
|
virMutex lock;
|
||||||
|
|
||||||
|
virNetworkObjList networks;
|
||||||
|
|
||||||
|
char *networkConfigDir;
|
||||||
|
char *networkAutostartDir;
|
||||||
|
char *stateDir;
|
||||||
|
char *pidDir;
|
||||||
|
char *dnsmasqStateDir;
|
||||||
|
char *radvdStateDir;
|
||||||
|
dnsmasqCapsPtr dnsmasqCaps;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _virNetworkDriverState virNetworkDriverState;
|
||||||
|
typedef virNetworkDriverState *virNetworkDriverStatePtr;
|
||||||
|
|
||||||
|
int networkCheckRouteCollision(virNetworkObjPtr network);
|
||||||
|
|
||||||
|
int networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef);
|
||||||
|
|
||||||
|
void networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef);
|
||||||
|
|
||||||
|
int networkAddRoutingFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef);
|
||||||
|
|
||||||
|
void networkRemoveRoutingFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef);
|
||||||
|
|
||||||
|
int networkAddGeneralFirewallRules(virNetworkObjPtr network);
|
||||||
|
|
||||||
|
void networkRemoveGeneralFirewallRules(virNetworkObjPtr network);
|
||||||
|
|
||||||
|
int networkAddIpSpecificFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef);
|
||||||
|
|
||||||
|
void networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef);
|
||||||
|
|
||||||
|
int networkAddFirewallRules(virNetworkObjPtr network);
|
||||||
|
|
||||||
|
void networkRemoveFirewallRules(virNetworkObjPtr network);
|
||||||
|
|
||||||
|
#endif /* __VIR_BRIDGE_DRIVER_PLATFORM_H__ */
|
Loading…
x
Reference in New Issue
Block a user