diff --git a/po/POTFILES.in b/po/POTFILES.in index 60ba68b95c..541335e395 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -81,6 +81,7 @@ src/util/dnsmasq.c src/util/hooks.c src/util/hostusb.c src/util/interface.c +src/util/iptables.c src/util/json.c src/util/macvtap.c src/util/network.c diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 0663d52f3c..d13f9e06c5 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -21,8 +21,6 @@ * Author: Daniel P. Berrange */ - - #include #include @@ -99,27 +97,18 @@ void virNetworkDefFree(virNetworkDefPtr def) VIR_FREE(def->name); VIR_FREE(def->bridge); VIR_FREE(def->forwardDev); - VIR_FREE(def->ipAddress); - VIR_FREE(def->network); - VIR_FREE(def->netmask); VIR_FREE(def->domain); - for (i = 0 ; i < def->nranges && def->ranges ; i++) { - VIR_FREE(def->ranges[i].start); - VIR_FREE(def->ranges[i].end); - } VIR_FREE(def->ranges); for (i = 0 ; i < def->nhosts && def->hosts ; i++) { VIR_FREE(def->hosts[i].mac); - VIR_FREE(def->hosts[i].ip); VIR_FREE(def->hosts[i].name); } VIR_FREE(def->hosts); VIR_FREE(def->tftproot); VIR_FREE(def->bootfile); - VIR_FREE(def->bootserver); VIR_FREE(def); } @@ -270,9 +259,8 @@ virNetworkDHCPRangeDefParseXML(virNetworkDefPtr def, virReportOOMError(); return -1; } - def->ranges[def->nranges].start = (char *)start; - def->ranges[def->nranges].end = (char *)end; - def->ranges[def->nranges].size = range; + def->ranges[def->nranges].start = saddr; + def->ranges[def->nranges].end = eaddr; def->nranges++; } else if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, BAD_CAST "host")) { @@ -321,20 +309,26 @@ virNetworkDHCPRangeDefParseXML(virNetworkDefPtr def, } def->hosts[def->nhosts].mac = (char *)mac; def->hosts[def->nhosts].name = (char *)name; - def->hosts[def->nhosts].ip = (char *)ip; + def->hosts[def->nhosts].ip = inaddr; def->nhosts++; } else if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, BAD_CAST "bootp")) { xmlChar *file; + xmlChar *server; + virSocketAddr inaddr; if (!(file = xmlGetProp(cur, BAD_CAST "file"))) { cur = cur->next; continue; } + server = xmlGetProp(cur, BAD_CAST "server"); + + if (virSocketParseAddr((const char *)server, &inaddr, AF_UNSPEC) < 0) + return -1; def->bootfile = (char *)file; - def->bootserver = (char *) xmlGetProp(cur, BAD_CAST "server"); + def->bootserver = inaddr; } cur = cur->next; @@ -378,6 +372,8 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) { virNetworkDefPtr def; char *tmp; + char *ipAddress; + char *netmask; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -421,49 +417,41 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0) def->delay = 0; - def->ipAddress = virXPathString("string(./ip[1]/@address)", ctxt); - def->netmask = virXPathString("string(./ip[1]/@netmask)", ctxt); - if (def->ipAddress && - def->netmask) { - virSocketAddr inaddress, innetmask; - char *netaddr; + ipAddress = virXPathString("string(./ip[1]/@address)", ctxt); + netmask = virXPathString("string(./ip[1]/@netmask)", ctxt); + if (ipAddress && + netmask) { xmlNodePtr ip; - if (virSocketParseAddr(def->ipAddress, &inaddress, AF_UNSPEC) < 0) + if (virSocketParseAddr(ipAddress, &def->ipAddress, AF_UNSPEC) < 0) goto error; - if (virSocketParseAddr(def->netmask, &innetmask, AF_UNSPEC) < 0) + if (virSocketParseAddr(netmask, &def->netmask, AF_UNSPEC) < 0) goto error; /* XXX someday we want IPv6, so will need to relax this */ - if (inaddress.data.sa.sa_family != AF_INET || - innetmask.data.sa.sa_family != AF_INET) { + if (!VIR_SOCKET_IS_FAMILY(&def->ipAddress, AF_INET) || + !VIR_SOCKET_IS_FAMILY(&def->netmask, AF_INET)) { virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only IPv4 addresses are supported")); goto error; } - inaddress.data.inet4.sin_addr.s_addr &= - innetmask.data.inet4.sin_addr.s_addr; - if (!(netaddr = virSocketFormatAddr(&inaddress))) - goto error; - - if (virAsprintf(&def->network, "%s/%s", netaddr, def->netmask) < 0) { - VIR_FREE(netaddr); - virReportOOMError(); - goto error; - } - VIR_FREE(netaddr); + def->network = def->ipAddress; + def->network.data.inet4.sin_addr.s_addr &= + def->netmask.data.inet4.sin_addr.s_addr; if ((ip = virXPathNode("./ip[1]", ctxt)) && virNetworkIPParseXML(def, ip) < 0) goto error; } + VIR_FREE(ipAddress); + VIR_FREE(netmask); /* IPv4 forwarding setup */ if (virXPathBoolean("count(./forward) > 0", ctxt)) { - if (!def->ipAddress || - !def->netmask) { + if (def->ipAddress.data.sa.sa_family != AF_INET || + def->netmask.data.sa.sa_family != AF_INET) { virNetworkReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Forwarding requested, but no IPv4 address/netmask provided")); goto error; @@ -583,14 +571,25 @@ char *virNetworkDefFormat(const virNetworkDefPtr def) if (def->domain) virBufferVSprintf(&buf, " \n", def->domain); - if (def->ipAddress || def->netmask) { + if (VIR_SOCKET_HAS_ADDR(&def->ipAddress) || + VIR_SOCKET_HAS_ADDR(&def->netmask)) { virBufferAddLit(&buf, " ipAddress) - virBufferVSprintf(&buf, " address='%s'", def->ipAddress); + if (VIR_SOCKET_HAS_ADDR(&def->ipAddress)) { + char *addr = virSocketFormatAddr(&def->ipAddress); + if (!addr) + goto error; + virBufferVSprintf(&buf, " address='%s'", addr); + VIR_FREE(addr); + } - if (def->netmask) - virBufferVSprintf(&buf, " netmask='%s'", def->netmask); + if (VIR_SOCKET_HAS_ADDR(&def->netmask)) { + char *addr = virSocketFormatAddr(&def->netmask); + if (!addr) + goto error; + virBufferVSprintf(&buf, " netmask='%s'", addr); + VIR_FREE(addr); + } virBufferAddLit(&buf, ">\n"); @@ -601,25 +600,44 @@ char *virNetworkDefFormat(const virNetworkDefPtr def) if ((def->nranges || def->nhosts)) { int i; virBufferAddLit(&buf, " \n"); - for (i = 0 ; i < def->nranges ; i++) + for (i = 0 ; i < def->nranges ; i++) { + char *saddr = virSocketFormatAddr(&def->ranges[i].start); + if (!saddr) + goto error; + char *eaddr = virSocketFormatAddr(&def->ranges[i].end); + if (!eaddr) { + VIR_FREE(saddr); + goto error; + } virBufferVSprintf(&buf, " \n", - def->ranges[i].start, def->ranges[i].end); + saddr, eaddr); + VIR_FREE(saddr); + VIR_FREE(eaddr); + } for (i = 0 ; i < def->nhosts ; i++) { virBufferAddLit(&buf, " hosts[i].mac) virBufferVSprintf(&buf, "mac='%s' ", def->hosts[i].mac); if (def->hosts[i].name) virBufferVSprintf(&buf, "name='%s' ", def->hosts[i].name); - if (def->hosts[i].ip) - virBufferVSprintf(&buf, "ip='%s' ", def->hosts[i].ip); + if (VIR_SOCKET_HAS_ADDR(&def->hosts[i].ip)) { + char *ipaddr = virSocketFormatAddr(&def->hosts[i].ip); + if (!ipaddr) + goto error; + virBufferVSprintf(&buf, "ip='%s' ", ipaddr); + VIR_FREE(ipaddr); + } virBufferAddLit(&buf, "/>\n"); } if (def->bootfile) { virBufferEscapeString(&buf, " bootfile); - if (def->bootserver) { - virBufferEscapeString(&buf, "server='%s' ", - def->bootserver); + if (VIR_SOCKET_HAS_ADDR(&def->bootserver)) { + char *ipaddr = virSocketFormatAddr(&def->bootserver); + if (!ipaddr) + goto error; + virBufferEscapeString(&buf, "server='%s' ", ipaddr); + VIR_FREE(ipaddr); } virBufferAddLit(&buf, "/>\n"); } @@ -639,6 +657,7 @@ char *virNetworkDefFormat(const virNetworkDefPtr def) no_memory: virReportOOMError(); + error: virBufferFreeAndReset(&buf); return NULL; } diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index c4956b6572..5a01bbf6ac 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -30,6 +30,7 @@ # include "internal.h" # include "threads.h" +# include "network.h" /* 2 possible types of forwarding */ enum virNetworkForwardType { @@ -43,9 +44,8 @@ enum virNetworkForwardType { typedef struct _virNetworkDHCPRangeDef virNetworkDHCPRangeDef; typedef virNetworkDHCPRangeDef *virNetworkDHCPRangeDefPtr; struct _virNetworkDHCPRangeDef { - char *start; - char *end; - int size; + virSocketAddr start; + virSocketAddr end; }; typedef struct _virNetworkDHCPHostDef virNetworkDHCPHostDef; @@ -53,7 +53,7 @@ typedef virNetworkDHCPHostDef *virNetworkDHCPHostDefPtr; struct _virNetworkDHCPHostDef { char *mac; char *name; - char *ip; + virSocketAddr ip; }; typedef struct _virNetworkDef virNetworkDef; @@ -70,9 +70,9 @@ struct _virNetworkDef { int forwardType; /* One of virNetworkForwardType constants */ char *forwardDev; /* Destination device for forwarding */ - char *ipAddress; /* Bridge IP address */ - char *netmask; - char *network; + virSocketAddr ipAddress; /* Bridge IP address */ + virSocketAddr netmask; + virSocketAddr network; unsigned int nranges; /* Zero or more dhcp ranges */ virNetworkDHCPRangeDefPtr ranges; @@ -82,7 +82,7 @@ struct _virNetworkDef { char *tftproot; char *bootfile; - char *bootserver; + virSocketAddr bootserver; }; typedef struct _virNetworkObj virNetworkObj; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 37ed32e701..5ee47eb0a7 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -143,7 +143,7 @@ networkFindActiveConfigs(struct network_driver *driver) { obj->active = 1; /* Finally try and read dnsmasq pid if any */ - if ((obj->def->ipAddress || + if ((VIR_SOCKET_HAS_ADDR(&obj->def->ipAddress) || obj->def->nranges) && virFileReadPid(NETWORK_PID_DIR, obj->def->name, &obj->dnsmasqPid) == 0) { @@ -375,8 +375,8 @@ networkSaveDnsmasqHostsfile(virNetworkObjPtr network, for (i = 0 ; i < network->def->nhosts ; i++) { virNetworkDHCPHostDefPtr host = &(network->def->hosts[i]); - if ((host->mac) && (host->ip)) - dnsmasqAddDhcpHost(dctx, host->mac, host->ip, host->name); + if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip)) + dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name); } if (dnsmasqSave(dctx) < 0) @@ -395,6 +395,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, char *pidfileArg; char buf[1024]; unsigned int ranges; + char *ipAddr; /* * For static-only DHCP, i.e. with no range but at least one host element, @@ -491,27 +492,46 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, * APPEND_ARG(*argv, i++, network->def->bridge); */ APPEND_ARG(*argv, i++, "--listen-address"); - APPEND_ARG(*argv, i++, network->def->ipAddress); + if (!(ipAddr = virSocketFormatAddr(&network->def->ipAddress))) + goto error; + APPEND_ARG_LIT(*argv, i++, ipAddr); APPEND_ARG(*argv, i++, "--except-interface"); APPEND_ARG(*argv, i++, "lo"); for (r = 0 ; r < network->def->nranges ; r++) { - snprintf(buf, sizeof(buf), "%s,%s", - network->def->ranges[r].start, - network->def->ranges[r].end); - + char *saddr = virSocketFormatAddr(&network->def->ranges[r].start); + if (!saddr) + goto error; + char *eaddr = virSocketFormatAddr(&network->def->ranges[r].end); + if (!eaddr) { + VIR_FREE(saddr); + goto error; + } + char *range; + int rc = virAsprintf(&range, "%s,%s", saddr, eaddr); + VIR_FREE(saddr); + VIR_FREE(eaddr); + if (rc < 0) + goto no_memory; APPEND_ARG(*argv, i++, "--dhcp-range"); - APPEND_ARG(*argv, i++, buf); - nbleases += network->def->ranges[r].size; + APPEND_ARG_LIT(*argv, i++, range); + nbleases += virSocketGetRange(&network->def->ranges[r].start, + &network->def->ranges[r].end); } if (!network->def->nranges && network->def->nhosts) { - snprintf(buf, sizeof(buf), "%s,static", - network->def->ipAddress); + char *ipaddr = virSocketFormatAddr(&network->def->ipAddress); + if (!ipaddr) + goto error; + char *range; + int rc = virAsprintf(&range, "%s,static", ipaddr); + VIR_FREE(ipaddr); + if (rc < 0) + goto no_memory; APPEND_ARG(*argv, i++, "--dhcp-range"); - APPEND_ARG(*argv, i++, buf); + APPEND_ARG_LIT(*argv, i++, range); } if (network->def->nranges > 0) { @@ -546,13 +566,22 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, APPEND_ARG(*argv, i++, network->def->tftproot); } if (network->def->bootfile) { - snprintf(buf, sizeof(buf), "%s%s%s", - network->def->bootfile, - network->def->bootserver ? ",," : "", - network->def->bootserver ? network->def->bootserver : ""); + char *ipaddr = NULL; + if (VIR_SOCKET_HAS_ADDR(&network->def->bootserver)) { + if (!(ipaddr = virSocketFormatAddr(&network->def->bootserver))) + goto error; + } + char *boot; + int rc = virAsprintf(&boot, "%s%s%s", + network->def->bootfile, + ipaddr ? ",," : "", + ipaddr ? ipaddr : ""); + VIR_FREE(ipaddr); + if (rc < 0) + goto no_memory; APPEND_ARG(*argv, i++, "--dhcp-boot"); - APPEND_ARG(*argv, i++, buf); + APPEND_ARG_LIT(*argv, i++, boot); } #undef APPEND_ARG @@ -560,12 +589,13 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, return 0; no_memory: + virReportOOMError(); + error: if (*argv) { for (i = 0; (*argv)[i]; i++) VIR_FREE((*argv)[i]); VIR_FREE(*argv); } - virReportOOMError(); return -1; } @@ -579,9 +609,9 @@ dhcpStartDhcpDaemon(virNetworkObjPtr network) network->dnsmasqPid = -1; - if (network->def->ipAddress == NULL) { + if (!VIR_SOCKET_IS_FAMILY(&network->def->ipAddress, AF_INET)) { networkReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot start dhcp daemon without IP address for server")); + "%s", _("cannot start dhcp daemon without IPv4 address for server")); return -1; } @@ -641,7 +671,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, int err; /* allow forwarding packets from the bridge interface */ if ((err = iptablesAddForwardAllowOut(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev))) { virReportSystemError(err, @@ -652,7 +682,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, /* allow forwarding packets to the bridge interface if they are part of an existing connection */ if ((err = iptablesAddForwardAllowRelatedIn(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev))) { virReportSystemError(err, @@ -686,7 +716,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, /* First the generic masquerade rule for other protocols */ if ((err = iptablesAddForwardMasquerade(driver->iptables, - network->def->network, + &network->def->network, network->def->forwardDev, NULL))) { virReportSystemError(err, @@ -697,7 +727,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, /* UDP with a source port restriction */ if ((err = iptablesAddForwardMasquerade(driver->iptables, - network->def->network, + &network->def->network, network->def->forwardDev, "udp"))) { virReportSystemError(err, @@ -708,7 +738,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, /* TCP with a source port restriction */ if ((err = iptablesAddForwardMasquerade(driver->iptables, - network->def->network, + &network->def->network, network->def->forwardDev, "tcp"))) { virReportSystemError(err, @@ -721,22 +751,22 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver, masqerr5: iptablesRemoveForwardMasquerade(driver->iptables, - network->def->network, + &network->def->network, network->def->forwardDev, "udp"); masqerr4: iptablesRemoveForwardMasquerade(driver->iptables, - network->def->network, + &network->def->network, network->def->forwardDev, NULL); masqerr3: iptablesRemoveForwardAllowRelatedIn(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev); masqerr2: iptablesRemoveForwardAllowOut(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev); masqerr1: @@ -749,7 +779,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver, int err; /* allow routing packets from the bridge interface */ if ((err = iptablesAddForwardAllowOut(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev))) { virReportSystemError(err, @@ -760,7 +790,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver, /* allow routing packets to the bridge interface */ if ((err = iptablesAddForwardAllowIn(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev))) { virReportSystemError(err, @@ -774,7 +804,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver, routeerr2: iptablesRemoveForwardAllowOut(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev); routeerr1: @@ -866,7 +896,8 @@ networkAddIptablesRules(struct network_driver *driver, * aborting, since not all iptables implementations support it). */ - if ((network->def->ipAddress || network->def->nranges) && + if ((VIR_SOCKET_HAS_ADDR(&network->def->ipAddress) || + network->def->nranges) && (iptablesAddOutputFixUdpChecksum(driver->iptables, network->def->bridge, 68) != 0)) { VIR_WARN("Could not add rule to fixup DHCP response checksums " @@ -904,36 +935,37 @@ networkAddIptablesRules(struct network_driver *driver, static void networkRemoveIptablesRules(struct network_driver *driver, virNetworkObjPtr network) { - if (network->def->ipAddress || network->def->nranges) { + if (VIR_SOCKET_HAS_ADDR(&network->def->ipAddress) || + network->def->nranges) { iptablesRemoveOutputFixUdpChecksum(driver->iptables, network->def->bridge, 68); } if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) { if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) { iptablesRemoveForwardMasquerade(driver->iptables, - network->def->network, + &network->def->network, network->def->forwardDev, "tcp"); iptablesRemoveForwardMasquerade(driver->iptables, - network->def->network, + &network->def->network, network->def->forwardDev, "udp"); iptablesRemoveForwardMasquerade(driver->iptables, - network->def->network, + &network->def->network, network->def->forwardDev, NULL); iptablesRemoveForwardAllowRelatedIn(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev); } else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE) iptablesRemoveForwardAllowIn(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev); iptablesRemoveForwardAllowOut(driver->iptables, - network->def->network, + &network->def->network, network->def->bridge, network->def->forwardDev); } @@ -1041,25 +1073,15 @@ static int networkCheckRouteCollision(virNetworkObjPtr network) unsigned int net_dest; char *cur, *buf = NULL; enum {MAX_ROUTE_SIZE = 1024*64}; - virSocketAddr inaddress, innetmask; - if (!network->def->ipAddress || !network->def->netmask) - return 0; - - if (virSocketParseAddr(network->def->ipAddress, &inaddress, AF_UNSPEC) < 0) - goto error; - - if (virSocketParseAddr(network->def->netmask, &innetmask, AF_UNSPEC) < 0) - goto error; - - if (inaddress.data.stor.ss_family != AF_INET || - innetmask.data.stor.ss_family != AF_INET) { + if (!VIR_SOCKET_IS_FAMILY(&network->def->ipAddress, AF_INET) || + !VIR_SOCKET_IS_FAMILY(&network->def->netmask, AF_INET)) { /* Only support collision check for IPv4 */ - goto out; + return 0; } - net_dest = (inaddress.data.inet4.sin_addr.s_addr & - innetmask.data.inet4.sin_addr.s_addr); + net_dest = (network->def->ipAddress.data.inet4.sin_addr.s_addr & + network->def->netmask.data.inet4.sin_addr.s_addr); /* Read whole routing table into memory */ if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0) @@ -1112,12 +1134,10 @@ static int networkCheckRouteCollision(virNetworkObjPtr network) addr_val &= mask_val; if ((net_dest == addr_val) && - (innetmask.data.inet4.sin_addr.s_addr == mask_val)) { + (network->def->netmask.data.inet4.sin_addr.s_addr == mask_val)) { networkReportError(VIR_ERR_INTERNAL_ERROR, - _("Network %s/%s is already in use by " - "interface %s"), - network->def->ipAddress, - network->def->netmask, iface); + _("Network is already in use by interface %s"), + iface); goto error; } } @@ -1160,19 +1180,21 @@ static int networkStartNetworkDaemon(struct network_driver *driver, if (brSetEnableSTP(driver->brctl, network->def->bridge, network->def->stp ? 1 : 0) < 0) goto err_delbr; - if (network->def->ipAddress && - (err = brSetInetAddress(driver->brctl, network->def->bridge, network->def->ipAddress))) { + if (VIR_SOCKET_HAS_ADDR(&network->def->ipAddress) && + (err = brSetInetAddress(driver->brctl, network->def->bridge, + &network->def->ipAddress))) { virReportSystemError(err, - _("cannot set IP address on bridge '%s' to '%s'"), - network->def->bridge, network->def->ipAddress); + _("cannot set IP address on bridge '%s'"), + network->def->bridge); goto err_delbr; } - if (network->def->netmask && - (err = brSetInetNetmask(driver->brctl, network->def->bridge, network->def->netmask))) { + if (VIR_SOCKET_HAS_ADDR(&network->def->netmask) && + (err = brSetInetNetmask(driver->brctl, network->def->bridge, + &network->def->netmask))) { virReportSystemError(err, - _("cannot set netmask on bridge '%s' to '%s'"), - network->def->bridge, network->def->netmask); + _("cannot set netmask on bridge '%s'"), + network->def->bridge); goto err_delbr; } @@ -1193,7 +1215,7 @@ static int networkStartNetworkDaemon(struct network_driver *driver, goto err_delbr2; } - if ((network->def->ipAddress || + if ((VIR_SOCKET_HAS_ADDR(&network->def->ipAddress) || network->def->nranges) && dhcpStartDhcpDaemon(network) < 0) goto err_delbr2; diff --git a/src/util/bridge.c b/src/util/bridge.c index b4a7e263d3..6a94ec0ec4 100644 --- a/src/util/bridge.c +++ b/src/util/bridge.c @@ -659,9 +659,8 @@ static int brSetInetAddr(brControl *ctl, const char *ifname, int cmd, - const char *addr) + virSocketAddr *addr) { - virSocketAddr sa; struct ifreq ifr; if (!ctl || !ctl->fd || !ifname || !addr) @@ -672,13 +671,10 @@ brSetInetAddr(brControl *ctl, if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL) return EINVAL; - if (virSocketParseAddr(addr, &sa, AF_UNSPEC) < 0) + if (!VIR_SOCKET_IS_FAMILY(addr, AF_INET)) return EINVAL; - if (sa.data.sa.sa_family != AF_INET) - return EINVAL; - - ifr.ifr_addr = sa.data.sa; + ifr.ifr_addr = addr->data.sa; if (ioctl(ctl->fd, cmd, &ifr) < 0) return errno; @@ -702,7 +698,7 @@ brSetInetAddr(brControl *ctl, int brSetInetAddress(brControl *ctl, const char *ifname, - const char *addr) + virSocketAddr *addr) { return brSetInetAddr(ctl, ifname, SIOCSIFADDR, addr); } @@ -723,7 +719,7 @@ brSetInetAddress(brControl *ctl, int brSetInetNetmask(brControl *ctl, const char *ifname, - const char *addr) + virSocketAddr *addr) { return brSetInetAddr(ctl, ifname, SIOCSIFNETMASK, addr); } diff --git a/src/util/bridge.h b/src/util/bridge.h index abcd1b52d7..3ef38d9dd5 100644 --- a/src/util/bridge.h +++ b/src/util/bridge.h @@ -28,6 +28,7 @@ # include # include +# include "network.h" /** * BR_IFNAME_MAXLEN: @@ -84,10 +85,10 @@ int brGetInterfaceUp (brControl *ctl, int brSetInetAddress (brControl *ctl, const char *ifname, - const char *addr); + virSocketAddr *addr); int brSetInetNetmask (brControl *ctl, const char *ifname, - const char *netmask); + virSocketAddr *addr); int brSetForwardDelay (brControl *ctl, const char *bridge, diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c index a96b524324..2cb25bf8f2 100644 --- a/src/util/dnsmasq.c +++ b/src/util/dnsmasq.c @@ -76,23 +76,28 @@ hostsfileFree(dnsmasqHostsfile *hostsfile) static int hostsfileAdd(dnsmasqHostsfile *hostsfile, const char *mac, - const char *ip, + virSocketAddr *ip, const char *name) { + char *ipstr; if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0) goto alloc_error; + if (!(ipstr = virSocketFormatAddr(ip))) + return -1; + if (name) { if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s,%s", - mac, ip, name) < 0) { + mac, ipstr, name) < 0) { goto alloc_error; } } else { if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s", - mac, ip) < 0) { + mac, ipstr) < 0) { goto alloc_error; } } + VIR_FREE(ipstr); hostsfile->nhosts++; @@ -100,7 +105,7 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile, alloc_error: virReportOOMError(); - + VIR_FREE(ipstr); return -1; } @@ -279,7 +284,7 @@ dnsmasqContextFree(dnsmasqContext *ctx) * dnsmasqAddDhcpHost: * @ctx: pointer to the dnsmasq context for each network * @mac: pointer to the string contains mac address of the host - * @ip: pointer to the string contains ip address of the host + * @ip: pointer to the socket address contains ip of the host * @name: pointer to the string contains hostname of the host or NULL * * Add dhcp-host entry. @@ -287,7 +292,7 @@ dnsmasqContextFree(dnsmasqContext *ctx) void dnsmasqAddDhcpHost(dnsmasqContext *ctx, const char *mac, - const char *ip, + virSocketAddr *ip, const char *name) { if (ctx->hostsfile) diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h index 121ccad73a..02a961fa90 100644 --- a/src/util/dnsmasq.h +++ b/src/util/dnsmasq.h @@ -22,6 +22,8 @@ #ifndef __DNSMASQ_H__ # define __DNSMASQ_H__ +# include "network.h" + typedef struct { /* @@ -50,7 +52,7 @@ dnsmasqContext * dnsmasqContextNew(const char *network_name, void dnsmasqContextFree(dnsmasqContext *ctx); void dnsmasqAddDhcpHost(dnsmasqContext *ctx, const char *mac, - const char *ip, + virSocketAddr *ip, const char *name); int dnsmasqSave(const dnsmasqContext *ctx); int dnsmasqDelete(const dnsmasqContext *ctx); diff --git a/src/util/iptables.c b/src/util/iptables.c index 1b905bb587..64efd45cdc 100644 --- a/src/util/iptables.c +++ b/src/util/iptables.c @@ -44,6 +44,10 @@ #include "virterror_internal.h" #include "logging.h" +#define iptablesError(code, ...) \ + virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + enum { ADD = 0, REMOVE @@ -324,27 +328,41 @@ iptablesRemoveUdpInput(iptablesContext *ctx, */ static int iptablesForwardAllowOut(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev, int action) { - if (physdev && physdev[0]) { - return iptablesAddRemoveRule(ctx->forward_filter, - action, - "--source", network, - "--in-interface", iface, - "--out-interface", physdev, - "--jump", "ACCEPT", - NULL); - } else { - return iptablesAddRemoveRule(ctx->forward_filter, - action, - "--source", network, - "--in-interface", iface, - "--jump", "ACCEPT", - NULL); + int ret; + char *networkstr; + + if (!VIR_SOCKET_IS_FAMILY(network, AF_INET)) { + iptablesError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Only IPv4 addresses can be used with iptables")); + return -1; } + + if (!(networkstr = virSocketFormatAddr(network))) + return -1; + + if (physdev && physdev[0]) { + ret = iptablesAddRemoveRule(ctx->forward_filter, + action, + "--source", networkstr, + "--in-interface", iface, + "--out-interface", physdev, + "--jump", "ACCEPT", + NULL); + } else { + ret = iptablesAddRemoveRule(ctx->forward_filter, + action, + "--source", networkstr, + "--in-interface", iface, + "--jump", "ACCEPT", + NULL); + } + VIR_FREE(networkstr); + return ret; } /** @@ -362,7 +380,7 @@ iptablesForwardAllowOut(iptablesContext *ctx, */ int iptablesAddForwardAllowOut(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev) { @@ -384,7 +402,7 @@ iptablesAddForwardAllowOut(iptablesContext *ctx, */ int iptablesRemoveForwardAllowOut(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev) { @@ -397,31 +415,45 @@ iptablesRemoveForwardAllowOut(iptablesContext *ctx, */ static int iptablesForwardAllowRelatedIn(iptablesContext *ctx, - const char *network, + virSocketAddr *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, - "--match", "state", - "--state", "ESTABLISHED,RELATED", - "--jump", "ACCEPT", - NULL); - } else { - return iptablesAddRemoveRule(ctx->forward_filter, - action, - "--destination", network, - "--out-interface", iface, - "--match", "state", - "--state", "ESTABLISHED,RELATED", - "--jump", "ACCEPT", - NULL); + int ret; + char *networkstr; + + if (!VIR_SOCKET_IS_FAMILY(network, AF_INET)) { + iptablesError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Only IPv4 addresses can be used with iptables")); + return -1; } + + if (!(networkstr = virSocketFormatAddr(network))) + return -1; + + if (physdev && physdev[0]) { + ret = iptablesAddRemoveRule(ctx->forward_filter, + action, + "--destination", networkstr, + "--in-interface", physdev, + "--out-interface", iface, + "--match", "state", + "--state", "ESTABLISHED,RELATED", + "--jump", "ACCEPT", + NULL); + } else { + ret = iptablesAddRemoveRule(ctx->forward_filter, + action, + "--destination", networkstr, + "--out-interface", iface, + "--match", "state", + "--state", "ESTABLISHED,RELATED", + "--jump", "ACCEPT", + NULL); + } + VIR_FREE(networkstr); + return ret; } /** @@ -439,7 +471,7 @@ iptablesForwardAllowRelatedIn(iptablesContext *ctx, */ int iptablesAddForwardAllowRelatedIn(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev) { @@ -461,7 +493,7 @@ iptablesAddForwardAllowRelatedIn(iptablesContext *ctx, */ int iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev) { @@ -472,27 +504,41 @@ iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx, */ static int iptablesForwardAllowIn(iptablesContext *ctx, - const char *network, + virSocketAddr *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); + int ret; + char *networkstr; + + if (!VIR_SOCKET_IS_FAMILY(network, AF_INET)) { + iptablesError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Only IPv4 addresses can be used with iptables")); + return -1; } + + if (!(networkstr = virSocketFormatAddr(network))) + return -1; + + if (physdev && physdev[0]) { + ret = iptablesAddRemoveRule(ctx->forward_filter, + action, + "--destination", networkstr, + "--in-interface", physdev, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); + } else { + ret = iptablesAddRemoveRule(ctx->forward_filter, + action, + "--destination", networkstr, + "--out-interface", iface, + "--jump", "ACCEPT", + NULL); + } + VIR_FREE(networkstr); + return ret; } /** @@ -510,7 +556,7 @@ iptablesForwardAllowIn(iptablesContext *ctx, */ int iptablesAddForwardAllowIn(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev) { @@ -532,7 +578,7 @@ iptablesAddForwardAllowIn(iptablesContext *ctx, */ int iptablesRemoveForwardAllowIn(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev) { @@ -698,50 +744,64 @@ iptablesRemoveForwardRejectIn(iptablesContext *ctx, */ static int iptablesForwardMasquerade(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *physdev, const char *protocol, int action) { + int ret; + char *networkstr; + + if (!VIR_SOCKET_IS_FAMILY(network, AF_INET)) { + iptablesError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Only IPv4 addresses can be used with iptables")); + return -1; + } + + if (!(networkstr = virSocketFormatAddr(network))) + return -1; + if (protocol && protocol[0]) { if (physdev && physdev[0]) { - return iptablesAddRemoveRule(ctx->nat_postrouting, - action, - "--source", network, - "-p", protocol, - "!", "--destination", network, - "--out-interface", physdev, - "--jump", "MASQUERADE", - "--to-ports", "1024-65535", - NULL); + ret = iptablesAddRemoveRule(ctx->nat_postrouting, + action, + "--source", networkstr, + "-p", protocol, + "!", "--destination", networkstr, + "--out-interface", physdev, + "--jump", "MASQUERADE", + "--to-ports", "1024-65535", + NULL); } else { - return iptablesAddRemoveRule(ctx->nat_postrouting, - action, - "--source", network, - "-p", protocol, - "!", "--destination", network, - "--jump", "MASQUERADE", - "--to-ports", "1024-65535", - NULL); + ret = iptablesAddRemoveRule(ctx->nat_postrouting, + action, + "--source", networkstr, + "-p", protocol, + "!", "--destination", networkstr, + "--jump", "MASQUERADE", + "--to-ports", "1024-65535", + NULL); } } else { if (physdev && physdev[0]) { - return iptablesAddRemoveRule(ctx->nat_postrouting, - action, - "--source", network, - "!", "--destination", network, - "--out-interface", physdev, - "--jump", "MASQUERADE", - NULL); + ret = iptablesAddRemoveRule(ctx->nat_postrouting, + action, + "--source", networkstr, + "!", "--destination", networkstr, + "--out-interface", physdev, + "--jump", "MASQUERADE", + NULL); } else { - return iptablesAddRemoveRule(ctx->nat_postrouting, - action, - "--source", network, - "!", "--destination", network, - "--jump", "MASQUERADE", - NULL); + ret = iptablesAddRemoveRule(ctx->nat_postrouting, + action, + "--source", networkstr, + "!", "--destination", networkstr, + "--jump", "MASQUERADE", + NULL); } } + VIR_FREE(networkstr); + return ret; } /** @@ -759,7 +819,7 @@ iptablesForwardMasquerade(iptablesContext *ctx, */ int iptablesAddForwardMasquerade(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *physdev, const char *protocol) { @@ -781,7 +841,7 @@ iptablesAddForwardMasquerade(iptablesContext *ctx, */ int iptablesRemoveForwardMasquerade(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *physdev, const char *protocol) { diff --git a/src/util/iptables.h b/src/util/iptables.h index 21ba667074..fd49685d68 100644 --- a/src/util/iptables.h +++ b/src/util/iptables.h @@ -22,6 +22,8 @@ #ifndef __QEMUD_IPTABLES_H__ # define __QEMUD_IPTABLES_H__ +# include "network.h" + typedef struct _iptablesContext iptablesContext; iptablesContext *iptablesContextNew (void); @@ -42,29 +44,29 @@ int iptablesRemoveUdpInput (iptablesContext *ctx, int port); int iptablesAddForwardAllowOut (iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev); int iptablesRemoveForwardAllowOut (iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev); int iptablesAddForwardAllowRelatedIn(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev); int iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev); int iptablesAddForwardAllowIn (iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev); int iptablesRemoveForwardAllowIn (iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *iface, const char *physdev); @@ -84,11 +86,11 @@ int iptablesRemoveForwardRejectIn (iptablesContext *ctx, const char *iface); int iptablesAddForwardMasquerade (iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *physdev, const char *protocol); int iptablesRemoveForwardMasquerade (iptablesContext *ctx, - const char *network, + virSocketAddr *network, const char *physdev, const char *protocol); int iptablesAddOutputFixUdpChecksum (iptablesContext *ctx, diff --git a/src/util/network.h b/src/util/network.h index 9f9a340d44..0900e29c2b 100644 --- a/src/util/network.h +++ b/src/util/network.h @@ -34,6 +34,12 @@ typedef struct { socklen_t len; } virSocketAddr; +# define VIR_SOCKET_HAS_ADDR(s) \ + ((s)->data.sa.sa_family != AF_UNSPEC) + +# define VIR_SOCKET_IS_FAMILY(s, f) \ + ((s)->data.sa.sa_family == f) + typedef virSocketAddr *virSocketAddrPtr; int virSocketParseAddr (const char *val,