Index: qemud/conf.c =================================================================== RCS file: /data/cvs/libvirt/qemud/conf.c,v retrieving revision 1.47 diff -u -p -r1.47 conf.c --- qemud/conf.c 30 Mar 2007 16:23:04 -0000 1.47 +++ qemud/conf.c 5 Apr 2007 00:51:54 -0000 @@ -32,6 +32,8 @@ #include #include #include +#include + #include #include @@ -44,7 +46,6 @@ #include "internal.h" #include "conf.h" #include "driver.h" -#include "iptables.h" #include "uuid.h" #include "buf.h" @@ -1127,15 +1128,6 @@ qemudNetworkIfaceConnect(struct qemud_se goto error; } - if (net->type == QEMUD_NET_NETWORK && network->def->forward) { - if ((err = iptablesAddPhysdevForward(server->iptables, ifname))) { - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, - "Failed to add iptables rule to allow bridging from '%s' :%s", - ifname, strerror(err)); - goto error; - } - } - snprintf(tapfdstr, sizeof(tapfdstr), "tap,fd=%d,script=,vlan=%d", tapfd, vlan); if (!(retval = strdup(tapfdstr))) @@ -1151,8 +1143,6 @@ qemudNetworkIfaceConnect(struct qemud_se return retval; no_memory: - if (net->type == QEMUD_NET_NETWORK && network->def->forward) - iptablesRemovePhysdevForward(server->iptables, ifname); qemudReportError(server, VIR_ERR_NO_MEMORY, "tapfds"); error: if (retval) @@ -1765,6 +1755,21 @@ static int qemudParseInetXML(struct qemu netmask = NULL; } + if (def->ipAddress[0] && def->netmask[0]) { + struct in_addr inaddress, innetmask; + char *netaddr; + + inet_aton((const char*)def->ipAddress, &inaddress); + inet_aton((const char*)def->netmask, &innetmask); + + inaddress.s_addr &= innetmask.s_addr; + + netaddr = inet_ntoa(inaddress); + + snprintf(def->network,sizeof(def->network)-1, + "%s/%s", netaddr, (const char *)def->netmask); + } + cur = node->children; while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE && @@ -1835,9 +1840,37 @@ static struct qemud_network_def *qemudPa } xmlXPathFreeObject(obj); + /* Parse bridge information */ + obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt); + if ((obj != NULL) && (obj->type == XPATH_NODESET) && + (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) { + if (!qemudParseBridgeXML(server, def, obj->nodesetval->nodeTab[0])) { + goto error; + } + } + xmlXPathFreeObject(obj); + + /* Parse IP information */ + obj = xmlXPathEval(BAD_CAST "/network/ip[1]", ctxt); + if ((obj != NULL) && (obj->type == XPATH_NODESET) && + (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) { + if (!qemudParseInetXML(server, def, obj->nodesetval->nodeTab[0])) { + goto error; + } + } + xmlXPathFreeObject(obj); + + /* IPv4 forwarding setup */ obj = xmlXPathEval(BAD_CAST "count(/network/forward) > 0", ctxt); if ((obj != NULL) && (obj->type == XPATH_BOOLEAN) && obj->boolval) { + if (!def->ipAddress[0] || + !def->netmask[0]) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, + "Forwarding requested, but no IPv4 address/netmask provided"); + goto error; + } + def->forward = 1; tmp = xmlXPathEval(BAD_CAST "string(/network/forward[1]/@dev)", ctxt); if ((tmp != NULL) && (tmp->type == XPATH_STRING) && @@ -1860,26 +1893,6 @@ static struct qemud_network_def *qemudPa } xmlXPathFreeObject(obj); - /* Parse bridge information */ - obj = xmlXPathEval(BAD_CAST "/network/bridge[1]", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) { - if (!qemudParseBridgeXML(server, def, obj->nodesetval->nodeTab[0])) { - goto error; - } - } - xmlXPathFreeObject(obj); - - /* Parse IP information */ - obj = xmlXPathEval(BAD_CAST "/network/ip[1]", ctxt); - if ((obj != NULL) && (obj->type == XPATH_NODESET) && - (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) { - if (!qemudParseInetXML(server, def, obj->nodesetval->nodeTab[0])) { - goto error; - } - } - xmlXPathFreeObject(obj); - xmlXPathFreeContext(ctxt); return def; @@ -2622,7 +2635,7 @@ char *qemudGenerateXML(struct qemud_serv char *qemudGenerateNetworkXML(struct qemud_server *server, - struct qemud_network *network ATTRIBUTE_UNUSED, + struct qemud_network *network, struct qemud_network_def *def) { bufferPtr buf = 0; unsigned char *uuid; @@ -2654,11 +2667,17 @@ char *qemudGenerateNetworkXML(struct qem } } - if ((def->bridge != '\0' || def->disableSTP || def->forwardDelay) && - bufferVSprintf(buf, " \n", - def->bridge, - def->disableSTP ? "off" : "on", - def->forwardDelay) < 0) + bufferAdd(buf, " bridge) < 0) + goto no_memory; + } else if (def->bridge[0]) { + if (bufferVSprintf(buf, " name='%s'", def->bridge) < 0) + goto no_memory; + } + if (bufferVSprintf(buf, " stp='%s' forwardDelay='%d' />\n", + def->disableSTP ? "off" : "on", + def->forwardDelay) < 0) goto no_memory; if (def->ipAddress[0] || def->netmask[0]) { Index: qemud/internal.h =================================================================== RCS file: /data/cvs/libvirt/qemud/internal.h,v retrieving revision 1.21 diff -u -p -r1.21 internal.h --- qemud/internal.h 16 Mar 2007 15:03:21 -0000 1.21 +++ qemud/internal.h 5 Apr 2007 00:51:54 -0000 @@ -250,6 +250,7 @@ struct qemud_network_def { char ipAddress[BR_INET_ADDR_MAXLEN]; char netmask[BR_INET_ADDR_MAXLEN]; + char network[BR_INET_ADDR_MAXLEN+BR_INET_ADDR_MAXLEN+1]; int nranges; struct qemud_dhcp_range_def *ranges; Index: qemud/iptables.c =================================================================== RCS file: /data/cvs/libvirt/qemud/iptables.c,v retrieving revision 1.9 diff -u -p -r1.9 iptables.c --- qemud/iptables.c 30 Mar 2007 16:25:02 -0000 1.9 +++ qemud/iptables.c 5 Apr 2007 00:51:54 -0000 @@ -656,49 +657,29 @@ iptablesRemoveUdpInput(iptablesContext * return iptablesInput(ctx, iface, port, REMOVE, 0); } -static int -iptablesPhysdevForward(iptablesContext *ctx, - const char *iface, - int action) -{ - return iptablesAddRemoveRule(ctx->forward_filter, - action, - "--match", "physdev", - "--physdev-in", iface, - "--jump", "ACCEPT", - NULL); -} - -int -iptablesAddPhysdevForward(iptablesContext *ctx, - const char *iface) -{ - return iptablesPhysdevForward(ctx, iface, ADD); -} - -int -iptablesRemovePhysdevForward(iptablesContext *ctx, - const char *iface) -{ - return iptablesPhysdevForward(ctx, iface, REMOVE); -} +/* Allow all traffic coming from the bridge, with a valid network address + * to proceed to WAN + */ static int -iptablesInterfaceForward(iptablesContext *ctx, +iptablesForwardAllowOut(iptablesContext *ctx, + const char *network, const char *iface, - const char *target, + const char *physdev, int action) { - if (target && target[0]) { + if (physdev && physdev[0]) { return iptablesAddRemoveRule(ctx->forward_filter, action, + "--source", network, "--in-interface", iface, - "--out-interface", target, + "--out-interface", physdev, "--jump", "ACCEPT", NULL); } else { return iptablesAddRemoveRule(ctx->forward_filter, action, + "--source", network, "--in-interface", iface, "--jump", "ACCEPT", NULL); @@ -706,31 +687,39 @@ iptablesInterfaceForward(iptablesContext } int -iptablesAddInterfaceForward(iptablesContext *ctx, +iptablesAddForwardAllowOut(iptablesContext *ctx, + const char *network, const char *iface, - const char *target) + const char *physdev) { - return iptablesInterfaceForward(ctx, iface, target, ADD); + return iptablesForwardAllowOut(ctx, network, iface, physdev, ADD); } int -iptablesRemoveInterfaceForward(iptablesContext *ctx, +iptablesRemoveForwardAllowOut(iptablesContext *ctx, + const char *network, const char *iface, - const char *target) + const char *physdev) { - return iptablesInterfaceForward(ctx, iface, target, REMOVE); + return iptablesForwardAllowOut(ctx, network, iface, physdev, REMOVE); } + +/* Allow all traffic destined to the bridge, with a valid network address + * and associated with an existing connection + */ static int -iptablesStateForward(iptablesContext *ctx, - const char *iface, - const char *target, - int action) +iptablesForwardAllowIn(iptablesContext *ctx, + const char *network, + const char *iface, + const char *physdev, + int action) { - if (target && target[0]) { + if (physdev && physdev[0]) { return iptablesAddRemoveRule(ctx->forward_filter, action, - "--in-interface", target, + "--destination", network, + "--in-interface", physdev, "--out-interface", iface, "--match", "state", "--state", "ESTABLISHED,RELATED", @@ -739,6 +728,7 @@ iptablesStateForward(iptablesContext *ct } else { return iptablesAddRemoveRule(ctx->forward_filter, action, + "--destination", network, "--out-interface", iface, "--match", "state", "--state", "ESTABLISHED,RELATED", @@ -748,56 +738,126 @@ iptablesStateForward(iptablesContext *ct } int -iptablesAddStateForward(iptablesContext *ctx, +iptablesAddForwardAllowIn(iptablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return iptablesForwardAllowIn(ctx, network, iface, physdev, ADD); +} + +int +iptablesRemoveForwardAllowIn(iptablesContext *ctx, + const char *network, + const char *iface, + const char *physdev) +{ + return iptablesForwardAllowIn(ctx, network, iface, physdev, REMOVE); +} + + + +/* Drop all traffic trying to forward from the bridge. + * ie the bridge is the in interface + */ +static int +iptablesForwardRejectOut(iptablesContext *ctx, + const char *iface, + int action) +{ + return iptablesAddRemoveRule(ctx->forward_filter, + action, + "--in-interface", iface, + "--jump", "REJECT", + NULL); +} + +int +iptablesAddForwardRejectOut(iptablesContext *ctx, + const char *iface) +{ + return iptablesForwardRejectOut(ctx, iface, ADD); +} + +int +iptablesRemoveForwardRejectOut(iptablesContext *ctx, + const char *iface) +{ + return iptablesForwardRejectOut(ctx, iface, REMOVE); +} + + + + +/* Drop all traffic trying to forward to the bridge. + * ie the bridge is the out interface + */ +static int +iptablesForwardRejectIn(iptablesContext *ctx, const char *iface, - const char *target) + int action) +{ + return iptablesAddRemoveRule(ctx->forward_filter, + action, + "--out-interface", iface, + "--jump", "REJECT", + NULL); +} + +int +iptablesAddForwardRejectIn(iptablesContext *ctx, + const char *iface) { - return iptablesStateForward(ctx, iface, target, ADD); + return iptablesForwardRejectIn(ctx, iface, ADD); } int -iptablesRemoveStateForward(iptablesContext *ctx, - const char *iface, - const char *target) +iptablesRemoveForwardRejectIn(iptablesContext *ctx, + const char *iface) { - return iptablesStateForward(ctx, iface, target, REMOVE); + return iptablesForwardRejectIn(ctx, iface, REMOVE); } + +/* Masquerade all traffic coming from the network associated + * with the bridge + */ static int -iptablesNonBridgedMasq(iptablesContext *ctx, - const char *target, +iptablesForwardMasquerade(iptablesContext *ctx, + const char *network, + const char *physdev, int action) { - if (target && target[0]) { + if (physdev && physdev[0]) { return iptablesAddRemoveRule(ctx->nat_postrouting, action, - "--out-interface", target, - "--match", "physdev", - "!", "--physdev-is-bridged", + "--source", network, + "--out-interface", physdev, "--jump", "MASQUERADE", NULL); } else { return iptablesAddRemoveRule(ctx->nat_postrouting, action, - "--match", "physdev", - "!", "--physdev-is-bridged", + "--source", network, "--jump", "MASQUERADE", NULL); } } int -iptablesAddNonBridgedMasq(iptablesContext *ctx, - const char *target) +iptablesAddForwardMasquerade(iptablesContext *ctx, + const char *network, + const char *physdev) { - return iptablesNonBridgedMasq(ctx, target, ADD); + return iptablesForwardMasquerade(ctx, network, physdev, ADD); } int -iptablesRemoveNonBridgedMasq(iptablesContext *ctx, - const char *target) +iptablesRemoveForwardMasquerade(iptablesContext *ctx, + const char *network, + const char *physdev) { - return iptablesNonBridgedMasq(ctx, target, REMOVE); + return iptablesForwardMasquerade(ctx, network, physdev, REMOVE); } /* Index: qemud/iptables.h =================================================================== RCS file: /data/cvs/libvirt/qemud/iptables.h,v retrieving revision 1.4 diff -u -p -r1.4 iptables.h --- qemud/iptables.h 30 Mar 2007 16:25:02 -0000 1.4 +++ qemud/iptables.h 5 Apr 2007 00:51:54 -0000 @@ -43,29 +43,40 @@ int iptablesRemoveUdpInput const char *iface, int port); -int iptablesAddPhysdevForward (iptablesContext *ctx, - const char *iface); -int iptablesRemovePhysdevForward (iptablesContext *ctx, - const char *iface); - -int iptablesAddInterfaceForward (iptablesContext *ctx, +int iptablesAddForwardAllowOut (iptablesContext *ctx, + const char *network, const char *iface, - const char *target); -int iptablesRemoveInterfaceForward (iptablesContext *ctx, + const char *physdev); +int iptablesRemoveForwardAllowOut (iptablesContext *ctx, + const char *network, const char *iface, - const char *target); + const char *physdev); -int iptablesAddStateForward (iptablesContext *ctx, +int iptablesAddForwardAllowIn (iptablesContext *ctx, + const char *network, const char *iface, - const char *target); -int iptablesRemoveStateForward (iptablesContext *ctx, + const char *physdev); +int iptablesRemoveForwardAllowIn (iptablesContext *ctx, + const char *network, const char *iface, - const char *target); + const char *physdev); + +int iptablesAddForwardRejectOut (iptablesContext *ctx, + const char *iface); +int iptablesRemoveForwardRejectOut (iptablesContext *ctx, + const char *iface); + +int iptablesAddForwardRejectIn (iptablesContext *ctx, + const char *iface); +int iptablesRemoveForwardRejectIn (iptablesContext *ctx, + const char *iface); -int iptablesAddNonBridgedMasq (iptablesContext *ctx, - const char *target); -int iptablesRemoveNonBridgedMasq (iptablesContext *ctx, - const char *target); +int iptablesAddForwardMasquerade (iptablesContext *ctx, + const char *network, + const char *physdev); +int iptablesRemoveForwardMasquerade (iptablesContext *ctx, + const char *network, + const char *physdev); #endif /* __QEMUD_IPTABLES_H__ */ Index: qemud/qemud.c =================================================================== RCS file: /data/cvs/libvirt/qemud/qemud.c,v retrieving revision 1.38 diff -u -p -r1.38 qemud.c --- qemud/qemud.c 4 Apr 2007 09:32:00 -0000 1.38 +++ qemud/qemud.c 5 Apr 2007 00:51:56 -0000 @@ -45,6 +45,7 @@ #include #include + #include #include "internal.h" @@ -1041,26 +1042,8 @@ static int qemudVMData(struct qemud_serv } } -static void -qemudNetworkIfaceDisconnect(struct qemud_server *server, - struct qemud_vm *vm ATTRIBUTE_UNUSED, - struct qemud_vm_net_def *net) { - struct qemud_network *network; - if (net->type != QEMUD_NET_NETWORK) - return; - - if (!(network = qemudFindNetworkByName(server, net->dst.network.name))) { - return; - } else if (network->bridge[0] == '\0') { - return; - } - - iptablesRemovePhysdevForward(server->iptables, net->dst.network.ifname); -} int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) { - struct qemud_vm_net_def *net; - if (!qemudIsActiveVM(vm)) return 0; @@ -1079,13 +1062,6 @@ int qemudShutdownVMDaemon(struct qemud_s vm->monitor = -1; server->nvmfds -= 2; - net = vm->def->nets; - while (net) { - if (net->type == QEMUD_NET_NETWORK) - qemudNetworkIfaceDisconnect(server, vm, net); - net = net->next; - } - if (waitpid(vm->pid, NULL, WNOHANG) != vm->pid) { kill(vm->pid, SIGKILL); if (waitpid(vm->pid, NULL, 0) != vm->pid) { @@ -1251,27 +1227,20 @@ qemudAddIptablesRules(struct qemud_serve return 1; } - /* allow bridging from the bridge interface itself */ - if ((err = iptablesAddPhysdevForward(server->iptables, network->bridge))) { - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, - "failed to add iptables rule to allow bridging from '%s' : %s\n", - network->bridge, strerror(err)); - goto err1; - } /* allow DHCP requests through to dnsmasq */ if ((err = iptablesAddTcpInput(server->iptables, network->bridge, 67))) { qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "failed to add iptables rule to allow DHCP requests from '%s' : %s\n", network->bridge, strerror(err)); - goto err2; + goto err1; } if ((err = iptablesAddUdpInput(server->iptables, network->bridge, 67))) { qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "failed to add iptables rule to allow DHCP requests from '%s' : %s\n", network->bridge, strerror(err)); - goto err3; + goto err2; } /* allow DNS requests through to dnsmasq */ @@ -1279,60 +1248,95 @@ qemudAddIptablesRules(struct qemud_serve qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "failed to add iptables rule to allow DNS requests from '%s' : %s\n", network->bridge, strerror(err)); - goto err4; + goto err3; } if ((err = iptablesAddUdpInput(server->iptables, network->bridge, 53))) { qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "failed to add iptables rule to allow DNS requests from '%s' : %s\n", network->bridge, strerror(err)); + goto err4; + } + + + /* Catch all rules to block forwarding to/from bridges */ + + if ((err = iptablesAddForwardRejectOut(server->iptables, network->bridge))) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, + "failed to add iptables rule to block outbound traffic from '%s' : %s\n", + network->bridge, strerror(err)); goto err5; } + if ((err = iptablesAddForwardRejectIn(server->iptables, network->bridge))) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, + "failed to add iptables rule to block inbound traffic to '%s' : %s\n", + network->bridge, strerror(err)); + goto err6; + } + /* The remaining rules are only needed for IP forwarding */ if (!network->def->forward) return 1; /* allow forwarding packets from the bridge interface */ - if ((err = iptablesAddInterfaceForward(server->iptables, network->bridge, network->def->forwardDev))) { + if ((err = iptablesAddForwardAllowOut(server->iptables, + network->def->network, + network->bridge, + network->def->forwardDev))) { qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "failed to add iptables rule to allow forwarding from '%s' : %s\n", network->bridge, strerror(err)); - goto err6; + goto err7; } /* allow forwarding packets to the bridge interface if they are part of an existing connection */ - if ((err = iptablesAddStateForward(server->iptables, network->bridge, network->def->forwardDev))) { + if ((err = iptablesAddForwardAllowIn(server->iptables, + network->def->network, + network->bridge, + network->def->forwardDev))) { qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "failed to add iptables rule to allow forwarding to '%s' : %s\n", network->bridge, strerror(err)); - goto err7; + goto err8; } /* enable masquerading */ - if ((err = iptablesAddNonBridgedMasq(server->iptables, network->def->forwardDev))) { + if ((err = iptablesAddForwardMasquerade(server->iptables, + network->def->network, + network->def->forwardDev))) { qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "failed to add iptables rule to enable masquerading : %s\n", strerror(err)); - goto err8; + goto err9; } return 1; + err9: + iptablesRemoveForwardAllowIn(server->iptables, + network->def->network, + network->bridge, + network->def->forwardDev); err8: - iptablesRemoveStateForward(server->iptables, network->bridge, network->def->forwardDev); + iptablesRemoveForwardAllowOut(server->iptables, + network->def->network, + network->bridge, + network->def->forwardDev); err7: - iptablesRemoveInterfaceForward(server->iptables, network->bridge, network->def->forwardDev); + iptablesRemoveForwardRejectIn(server->iptables, + network->bridge); err6: - iptablesRemoveUdpInput(server->iptables, network->bridge, 53); + iptablesRemoveForwardRejectOut(server->iptables, + network->bridge); err5: - iptablesRemoveTcpInput(server->iptables, network->bridge, 53); + iptablesRemoveUdpInput(server->iptables, network->bridge, 53); err4: - iptablesRemoveUdpInput(server->iptables, network->bridge, 67); + iptablesRemoveTcpInput(server->iptables, network->bridge, 53); err3: - iptablesRemoveTcpInput(server->iptables, network->bridge, 67); + iptablesRemoveUdpInput(server->iptables, network->bridge, 67); err2: - iptablesRemovePhysdevForward(server->iptables, network->bridge); + iptablesRemoveTcpInput(server->iptables, network->bridge, 67); err1: return 0; } @@ -1341,15 +1345,24 @@ static void qemudRemoveIptablesRules(struct qemud_server *server, struct qemud_network *network) { if (network->def->forward) { - iptablesRemoveNonBridgedMasq(server->iptables, network->def->forwardDev); - iptablesRemoveStateForward(server->iptables, network->bridge, network->def->forwardDev); - iptablesRemoveInterfaceForward(server->iptables, network->bridge, network->def->forwardDev); + iptablesRemoveForwardMasquerade(server->iptables, + network->def->network, + network->def->forwardDev); + iptablesRemoveForwardAllowIn(server->iptables, + network->def->network, + network->bridge, + network->def->forwardDev); + iptablesRemoveForwardAllowOut(server->iptables, + network->def->network, + network->bridge, + network->def->forwardDev); } + iptablesRemoveForwardRejectIn(server->iptables, network->bridge); + iptablesRemoveForwardRejectOut(server->iptables, network->bridge); iptablesRemoveUdpInput(server->iptables, network->bridge, 53); iptablesRemoveTcpInput(server->iptables, network->bridge, 53); iptablesRemoveUdpInput(server->iptables, network->bridge, 67); iptablesRemoveTcpInput(server->iptables, network->bridge, 67); - iptablesRemovePhysdevForward(server->iptables, network->bridge); } static int