diff --git a/AUTHORS b/AUTHORS index 1c570bcb5c..b4e9c9d653 100644 --- a/AUTHORS +++ b/AUTHORS @@ -40,6 +40,7 @@ Patches have also been contributed by: Chris Lalancette Guido Guenther Daniel Hokka Zakrisson + Mads Chr. Olesen [....send patches to get your name here....] diff --git a/ChangeLog b/ChangeLog index ff060ad672..77375a340b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,14 @@ -Fri Mar 27 13:55:56 EDT 2008 Daniel P. Berrange +Fri Mar 28 16:34:56 EDT 2008 Daniel P. Berrange + + * src/network.rng: Add new routed networking schema + * src/iptables.c, src/iptables.h: Add iptablesAddForwardAllowRelatedIn + and iptablesRemoveForwardAllowRelatedIn + * src/qemu_conf.h: Add attribute for routed networking + * src/qemu_conf.c: Parse / format new networking attributes + * src/qemu_driver.c: Support routed networking config + (patches from Mads Chr. Olesen) + +Fri Mar 28 13:55:56 EDT 2008 Daniel P. Berrange * src/storage_conf.c: Fix XML output tag for FS storage pools directory path diff --git a/docs/network.rng b/docs/network.rng index a3a4b88367..d84bb2d01f 100644 --- a/docs/network.rng +++ b/docs/network.rng @@ -56,6 +56,14 @@ rest of the network --> + + + + nat + routed + + + diff --git a/src/iptables.c b/src/iptables.c index 6390e49c6b..c08a00e74c 100644 --- a/src/iptables.c +++ b/src/iptables.c @@ -793,7 +793,7 @@ iptablesRemoveForwardAllowOut(iptablesContext *ctx, * and associated with an existing connection */ static int -iptablesForwardAllowIn(iptablesContext *ctx, +iptablesForwardAllowRelatedIn(iptablesContext *ctx, const char *network, const char *iface, const char *physdev, @@ -821,6 +821,77 @@ iptablesForwardAllowIn(iptablesContext *ctx, } } +/** + * iptablesAddForwardAllowRelatedIn: + * @ctx: pointer to the IP table context + * @network: the source network name + * @iface: the output interface name + * @physdev: the physical input device or NULL + * + * Add rules to the IP table context to allow the traffic for the + * network @network on @physdev device to be forwarded to + * interface @iface, if it is part of an existing connection. + * + * Returns 0 in case of success or an error code otherwise + */ +int +iptablesAddForwardAllowRelatedIn(iptablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return iptablesForwardAllowRelatedIn(ctx, network, iface, physdev, ADD); +} + +/** + * iptablesRemoveForwardAllowRelatedIn: + * @ctx: pointer to the IP table context + * @network: the source network name + * @iface: the output interface name + * @physdev: the physical input device or NULL + * + * Remove rules from the IP table context hence forbidding the traffic for + * network @network on @physdev device to be forwarded to + * interface @iface, if it is part of an existing connection. + * + * Returns 0 in case of success or an error code otherwise + */ +int +iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return iptablesForwardAllowRelatedIn(ctx, network, iface, physdev, REMOVE); +} + +/* Allow all traffic destined to the bridge, with a valid network address + */ +static int +iptablesForwardAllowIn(iptablesContext *ctx, + const char *network, + const char *iface, + const char *physdev, + int action) +{ + if (physdev && physdev[0]) { + return iptablesAddRemoveRule(ctx->forward_filter, + action, + "--destination", network, + "--in-interface", physdev, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); + } else { + return iptablesAddRemoveRule(ctx->forward_filter, + action, + "--destination", network, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); + } +} + /** * iptablesAddForwardAllowIn: * @ctx: pointer to the IP table context diff --git a/src/iptables.h b/src/iptables.h index 6fe017428e..e33513ec1a 100644 --- a/src/iptables.h +++ b/src/iptables.h @@ -55,6 +55,15 @@ int iptablesRemoveForwardAllowOut (iptablesContext *ctx, const char *iface, const char *physdev); +int iptablesAddForwardAllowRelatedIn(iptablesContext *ctx, + const char *network, + const char *iface, + const char *physdev); +int iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx, + const char *network, + const char *iface, + const char *physdev); + int iptablesAddForwardAllowIn (iptablesContext *ctx, const char *network, const char *iface, diff --git a/src/qemu_conf.c b/src/qemu_conf.c index bafea8c9fd..6ff0852f37 100644 --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -2521,6 +2521,17 @@ static struct qemud_network_def *qemudParseNetworkXML(virConnectPtr conn, } def->forward = 1; + + tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@mode)", ctxt); + if ((tmp != NULL) && (tmp->type == XPATH_STRING) && + (tmp->stringval != NULL) && (xmlStrEqual(tmp->stringval, BAD_CAST "route"))) { + def->forwardMode = QEMUD_NET_FORWARD_ROUTE; + } else { + def->forwardMode = QEMUD_NET_FORWARD_NAT; + } + xmlXPathFreeObject(tmp); + tmp = NULL; + tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@dev)", ctxt); if ((tmp != NULL) && (tmp->type == XPATH_STRING) && (tmp->stringval != NULL) && (tmp->stringval[0] != 0)) { @@ -3160,10 +3171,10 @@ char *qemudGenerateNetworkXML(virConnectPtr conn, if (def->forward) { if (def->forwardDev[0]) { - virBufferVSprintf(buf, " \n", - def->forwardDev); + virBufferVSprintf(buf, " \n", + def->forwardDev, (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat")); } else { - virBufferAddLit(buf, " \n"); + virBufferVSprintf(buf, " \n", (def->forwardMode == QEMUD_NET_FORWARD_ROUTE ? "route" : "nat")); } } diff --git a/src/qemu_conf.h b/src/qemu_conf.h index c1aae75651..f52b359b43 100644 --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -83,6 +83,12 @@ enum qemud_vm_net_type { QEMUD_NET_BRIDGE, }; +/* 2 possible types of forwarding */ +enum qemud_vm_net_forward_type { + QEMUD_NET_FORWARD_NAT, + QEMUD_NET_FORWARD_ROUTE, +}; + #define QEMUD_MAX_NAME_LEN 50 #define QEMUD_MAX_XML_LEN 4096 #define QEMUD_MAX_ERROR_LEN 1024 @@ -266,6 +272,7 @@ struct qemud_network_def { int forwardDelay; int forward; + int forwardMode; /* From qemud_vm_net_forward_type */ char forwardDev[BR_IFNAME_MAXLEN]; char ipAddress[BR_INET_ADDR_MAXLEN]; diff --git a/src/qemu_driver.c b/src/qemu_driver.c index d68f0791c0..3c6a18dd46 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -948,6 +948,98 @@ dhcpStartDhcpDaemon(virConnectPtr conn, return ret; } +static int +qemudAddMasqueradingIptablesRules(virConnectPtr conn, + struct qemud_driver *driver, + struct qemud_network *network) { + int err; + /* allow forwarding packets from the bridge interface */ + if ((err = iptablesAddForwardAllowOut(driver->iptables, + network->def->network, + network->bridge, + network->def->forwardDev))) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to add iptables rule to allow forwarding from '%s' : %s\n"), + network->bridge, strerror(err)); + goto masqerr1; + } + + /* allow forwarding packets to the bridge interface if they are part of an existing connection */ + if ((err = iptablesAddForwardAllowRelatedIn(driver->iptables, + network->def->network, + network->bridge, + network->def->forwardDev))) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to add iptables rule to allow forwarding to '%s' : %s\n"), + network->bridge, strerror(err)); + goto masqerr2; + } + + /* enable masquerading */ + if ((err = iptablesAddForwardMasquerade(driver->iptables, + network->def->network, + network->def->forwardDev))) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to add iptables rule to enable masquerading : %s\n"), + strerror(err)); + goto masqerr3; + } + + return 1; + + masqerr3: + iptablesRemoveForwardAllowRelatedIn(driver->iptables, + network->def->network, + network->bridge, + network->def->forwardDev); + masqerr2: + iptablesRemoveForwardAllowOut(driver->iptables, + network->def->network, + network->bridge, + network->def->forwardDev); + masqerr1: + return 0; +} + +static int +qemudAddRoutingIptablesRules(virConnectPtr conn, + struct qemud_driver *driver, + struct qemud_network *network) { + int err; + /* allow routing packets from the bridge interface */ + if ((err = iptablesAddForwardAllowOut(driver->iptables, + network->def->network, + network->bridge, + network->def->forwardDev))) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to add iptables rule to allow routing from '%s' : %s\n"), + network->bridge, strerror(err)); + goto routeerr1; + } + + /* allow routing packets to the bridge interface */ + if ((err = iptablesAddForwardAllowIn(driver->iptables, + network->def->network, + network->bridge, + network->def->forwardDev))) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to add iptables rule to allow routing to '%s' : %s\n"), + network->bridge, strerror(err)); + goto routeerr2; + } + + return 1; + + + routeerr2: + iptablesRemoveForwardAllowOut(driver->iptables, + network->def->network, + network->bridge, + network->def->forwardDev); + routeerr1: + return 0; +} + static int qemudAddIptablesRules(virConnectPtr conn, struct qemud_driver *driver, @@ -1023,53 +1115,17 @@ qemudAddIptablesRules(virConnectPtr conn, return 1; } - /* allow forwarding packets from the bridge interface */ - if ((err = iptablesAddForwardAllowOut(driver->iptables, - network->def->network, - network->bridge, - network->def->forwardDev))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to add iptables rule to allow forwarding from '%s' : %s"), - network->bridge, strerror(err)); - goto err8; + /* If masquerading is enabled, set up the rules*/ + if (network->def->forwardMode == QEMUD_NET_FORWARD_NAT) { + if (qemudAddMasqueradingIptablesRules(conn, driver, network)) + return 1; + } + /* else if routing is enabled, set up the rules*/ + else if (network->def->forwardMode == QEMUD_NET_FORWARD_ROUTE) { + if (qemudAddRoutingIptablesRules(conn, driver, network)) + return 1; } - /* allow forwarding packets to the bridge interface if they are part of an existing connection */ - if ((err = iptablesAddForwardAllowIn(driver->iptables, - network->def->network, - network->bridge, - network->def->forwardDev))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to add iptables rule to allow forwarding to '%s' : %s"), - network->bridge, strerror(err)); - goto err9; - } - - /* enable masquerading */ - if ((err = iptablesAddForwardMasquerade(driver->iptables, - network->def->network, - network->def->forwardDev))) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to add iptables rule to enable masquerading : %s"), - strerror(err)); - goto err10; - } - - iptablesSaveRules(driver->iptables); - - return 1; - - err10: - iptablesRemoveForwardAllowIn(driver->iptables, - network->def->network, - network->bridge, - network->def->forwardDev); - err9: - iptablesRemoveForwardAllowOut(driver->iptables, - network->def->network, - network->bridge, - network->def->forwardDev); - err8: iptablesRemoveForwardAllowCross(driver->iptables, network->bridge); err7: