mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
Change virtual network XML parsing/formatting to support IPv6
This commit adds support for IPv6 parsing and formatting to the virtual network XML parser, including moving around data definitions to allow for multiple <ip> elements on a single network, but only changes the consumers of this API to accommodate for the changes in API/structure, not to add any actual IPv6 functionality. That will come in a later patch - this patch attempts to maintain the same final functionality in both drivers that use the network XML parser - vbox and "bridge" (the Linux bridge-based driver used by the qemu hypervisor driver). * src/libvirt_private.syms: Add new private API functions. * src/conf/network_conf.[ch]: Change C data structure and parsing/formatting. * src/network/bridge_driver.c: Update to use new parser/formatter. * src/vbox/vbox_tmpl.c: update to use new parser/formatter * docs/schemas/network.rng: changes to the schema - * there can now be more than one <ip> element. * ip address is now an ip-addr (ipv4 or ipv6) rather than ipv4-addr * new optional "prefix" attribute that can be used in place of "netmask" * new optional "family" attribute - "ipv4" or "ipv6" (will default to ipv4) * define data types for the above * tests/networkxml2xml(in|out)/nat-network.xml: add multiple <ip> elements (including IPv6) to a single network definition to verify they are being correctly parsed and formatted.
This commit is contained in:
parent
008abeeeb9
commit
a950dd2a31
docs/schemas
src
tests
@ -80,15 +80,21 @@
|
|||||||
</optional>
|
</optional>
|
||||||
|
|
||||||
<!-- <ip> element -->
|
<!-- <ip> element -->
|
||||||
<optional>
|
<zeroOrMore>
|
||||||
<!-- The IP element sets up NAT'ing and an optional DHCP server
|
<!-- The IP element sets up NAT'ing and an optional DHCP server
|
||||||
local to the host. -->
|
local to the host. -->
|
||||||
<element name="ip">
|
<element name="ip">
|
||||||
<optional>
|
<optional>
|
||||||
<attribute name="address"><ref name="ipv4-addr"/></attribute>
|
<attribute name="address"><ref name="ip-addr"/></attribute>
|
||||||
</optional>
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<attribute name="netmask"><ref name="ipv4-addr"/></attribute>
|
<choice>
|
||||||
|
<attribute name="netmask"><ref name="ipv4-addr"/></attribute>
|
||||||
|
<attribute name="prefix"><ref name="ip-prefix"/></attribute>
|
||||||
|
</choice>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="family"><ref name="addr-family"/></attribute>
|
||||||
</optional>
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<element name="tftp">
|
<element name="tftp">
|
||||||
@ -123,7 +129,7 @@
|
|||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</zeroOrMore>
|
||||||
</interleave>
|
</interleave>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
@ -135,6 +141,33 @@
|
|||||||
</data>
|
</data>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
<!-- Based on http://blog.mes-stats.fr/2008/10/09/regex-ipv4-et-ipv6 -->
|
||||||
|
<define name='ipv6-addr'>
|
||||||
|
<data type='string'>
|
||||||
|
<!-- To understand this better, take apart the toplevel '|'s -->
|
||||||
|
<param name="pattern">(([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([1-9][0-9])|([0-9]))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([1-9][0-9])|([0-9])))|(([0-9A-Fa-f]{1,4}:){0,5}:(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([1-9][0-9])|([0-9]))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([1-9][0-9])|([0-9])))|(::([0-9A-Fa-f]{1,4}:){0,5}(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([1-9][0-9])|([0-9]))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([1-9][0-9])|([0-9])))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)</param>
|
||||||
|
</data>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name='ip-addr'>
|
||||||
|
<choice>
|
||||||
|
<ref name='ipv4-addr'/>
|
||||||
|
<ref name='ipv6-addr'/>
|
||||||
|
</choice>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name='ip-prefix'>
|
||||||
|
<data type='unsignedInt'>
|
||||||
|
<param name="maxInclusive">128</param>
|
||||||
|
</data>
|
||||||
|
</define>
|
||||||
|
|
||||||
|
<define name='addr-family'>
|
||||||
|
<data type='string'>
|
||||||
|
<param name="pattern">(ipv4)|(ipv6)</param>
|
||||||
|
</data>
|
||||||
|
</define>
|
||||||
|
|
||||||
<!-- a 6 byte MAC address in ASCII-hex format, eg "12:34:56:78:9A:BC" -->
|
<!-- a 6 byte MAC address in ASCII-hex format, eg "12:34:56:78:9A:BC" -->
|
||||||
<define name='mac-addr'>
|
<define name='mac-addr'>
|
||||||
<data type='string'>
|
<data type='string'>
|
||||||
|
@ -87,9 +87,26 @@ virNetworkObjPtr virNetworkFindByName(const virNetworkObjListPtr nets,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void virNetworkIpDefClear(virNetworkIpDefPtr def)
|
||||||
|
{
|
||||||
|
int ii;
|
||||||
|
|
||||||
|
VIR_FREE(def->family);
|
||||||
|
VIR_FREE(def->ranges);
|
||||||
|
|
||||||
|
for (ii = 0 ; ii < def->nhosts && def->hosts ; ii++) {
|
||||||
|
VIR_FREE(def->hosts[ii].mac);
|
||||||
|
VIR_FREE(def->hosts[ii].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_FREE(def->hosts);
|
||||||
|
VIR_FREE(def->tftproot);
|
||||||
|
VIR_FREE(def->bootfile);
|
||||||
|
}
|
||||||
|
|
||||||
void virNetworkDefFree(virNetworkDefPtr def)
|
void virNetworkDefFree(virNetworkDefPtr def)
|
||||||
{
|
{
|
||||||
int i;
|
int ii;
|
||||||
|
|
||||||
if (!def)
|
if (!def)
|
||||||
return;
|
return;
|
||||||
@ -99,16 +116,10 @@ void virNetworkDefFree(virNetworkDefPtr def)
|
|||||||
VIR_FREE(def->forwardDev);
|
VIR_FREE(def->forwardDev);
|
||||||
VIR_FREE(def->domain);
|
VIR_FREE(def->domain);
|
||||||
|
|
||||||
VIR_FREE(def->ranges);
|
for (ii = 0 ; ii < def->nips && def->ips ; ii++) {
|
||||||
|
virNetworkIpDefClear(&def->ips[ii]);
|
||||||
for (i = 0 ; i < def->nhosts && def->hosts ; i++) {
|
|
||||||
VIR_FREE(def->hosts[i].mac);
|
|
||||||
VIR_FREE(def->hosts[i].name);
|
|
||||||
}
|
}
|
||||||
VIR_FREE(def->hosts);
|
VIR_FREE(def->ips);
|
||||||
|
|
||||||
VIR_FREE(def->tftproot);
|
|
||||||
VIR_FREE(def->bootfile);
|
|
||||||
|
|
||||||
VIR_FREE(def);
|
VIR_FREE(def);
|
||||||
}
|
}
|
||||||
@ -207,21 +218,48 @@ void virNetworkRemoveInactive(virNetworkObjListPtr nets,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return ips[index], or NULL if there aren't enough ips */
|
||||||
|
virNetworkIpDefPtr
|
||||||
|
virNetworkDefGetIpByIndex(const virNetworkDefPtr def,
|
||||||
|
int family, size_t n)
|
||||||
|
{
|
||||||
|
int ii;
|
||||||
|
|
||||||
|
if (!def->ips || n >= def->nips)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (family == AF_UNSPEC) {
|
||||||
|
return &def->ips[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the nth ip of type "family" */
|
||||||
|
for (ii = 0; ii < def->nips; ii++) {
|
||||||
|
if (VIR_SOCKET_IS_FAMILY(&def->ips[ii].address, family)
|
||||||
|
&& (n-- <= 0)) {
|
||||||
|
return &def->ips[ii];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* failed to find enough of the right family */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* return number of 1 bits in netmask for the network's ipAddress,
|
/* return number of 1 bits in netmask for the network's ipAddress,
|
||||||
* or -1 on error
|
* or -1 on error
|
||||||
*/
|
*/
|
||||||
int virNetworkDefPrefix(const virNetworkDefPtr def)
|
int virNetworkIpDefPrefix(const virNetworkIpDefPtr def)
|
||||||
{
|
{
|
||||||
if (VIR_SOCKET_HAS_ADDR(&def->netmask)) {
|
if (def->prefix > 0) {
|
||||||
|
return def->prefix;
|
||||||
|
} else if (VIR_SOCKET_HAS_ADDR(&def->netmask)) {
|
||||||
return virSocketGetNumNetmaskBits(&def->netmask);
|
return virSocketGetNumNetmaskBits(&def->netmask);
|
||||||
} else if (VIR_SOCKET_IS_FAMILY(&def->ipAddress, AF_INET)) {
|
} else if (VIR_SOCKET_IS_FAMILY(&def->address, AF_INET)) {
|
||||||
/* Return the natural prefix for the network's ip address.
|
/* Return the natural prefix for the network's ip address.
|
||||||
* On Linux we could use the IN_CLASSx() macros, but those
|
* On Linux we could use the IN_CLASSx() macros, but those
|
||||||
* aren't guaranteed on all platforms, so we just deal with
|
* aren't guaranteed on all platforms, so we just deal with
|
||||||
* the bits ourselves.
|
* the bits ourselves.
|
||||||
*/
|
*/
|
||||||
unsigned char octet
|
unsigned char octet
|
||||||
= ntohl(def->ipAddress.data.inet4.sin_addr.s_addr) >> 24;
|
= ntohl(def->address.data.inet4.sin_addr.s_addr) >> 24;
|
||||||
if ((octet & 0x80) == 0) {
|
if ((octet & 0x80) == 0) {
|
||||||
/* Class A network */
|
/* Class A network */
|
||||||
return 8;
|
return 8;
|
||||||
@ -233,6 +271,8 @@ int virNetworkDefPrefix(const virNetworkDefPtr def)
|
|||||||
return 24;
|
return 24;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
} else if (VIR_SOCKET_IS_FAMILY(&def->address, AF_INET6)) {
|
||||||
|
return 64;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -241,22 +281,23 @@ int virNetworkDefPrefix(const virNetworkDefPtr def)
|
|||||||
* definition, based on either the definition's netmask, or its
|
* definition, based on either the definition's netmask, or its
|
||||||
* prefix. Return -1 on error (and set the netmask family to AF_UNSPEC)
|
* prefix. Return -1 on error (and set the netmask family to AF_UNSPEC)
|
||||||
*/
|
*/
|
||||||
int virNetworkDefNetmask(const virNetworkDefPtr def,
|
int virNetworkIpDefNetmask(const virNetworkIpDefPtr def,
|
||||||
virSocketAddrPtr netmask)
|
virSocketAddrPtr netmask)
|
||||||
{
|
{
|
||||||
if (VIR_SOCKET_IS_FAMILY(&def->netmask, AF_INET)) {
|
if (VIR_SOCKET_IS_FAMILY(&def->netmask, AF_INET)) {
|
||||||
*netmask = def->netmask;
|
*netmask = def->netmask;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return virSocketAddrPrefixToNetmask(virNetworkDefPrefix(def), netmask,
|
return virSocketAddrPrefixToNetmask(virNetworkIpDefPrefix(def), netmask,
|
||||||
VIR_SOCKET_FAMILY(&def->ipAddress));
|
VIR_SOCKET_FAMILY(&def->address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virNetworkDHCPRangeDefParseXML(virNetworkDefPtr def,
|
virNetworkDHCPRangeDefParseXML(virNetworkIpDefPtr def,
|
||||||
xmlNodePtr node) {
|
xmlNodePtr node)
|
||||||
|
{
|
||||||
|
|
||||||
xmlNodePtr cur;
|
xmlNodePtr cur;
|
||||||
|
|
||||||
@ -390,33 +431,147 @@ virNetworkDHCPRangeDefParseXML(virNetworkDefPtr def,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virNetworkIPParseXML(virNetworkDefPtr def,
|
virNetworkIPParseXML(const char *networkName,
|
||||||
xmlNodePtr node) {
|
virNetworkIpDefPtr def,
|
||||||
xmlNodePtr cur;
|
xmlNodePtr node,
|
||||||
|
xmlXPathContextPtr ctxt)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* virNetworkIpDef object is already allocated as part of an array.
|
||||||
|
* On failure clear it out, but don't free it.
|
||||||
|
*/
|
||||||
|
|
||||||
cur = node->children;
|
xmlNodePtr cur, save;
|
||||||
while (cur != NULL) {
|
char *address = NULL, *netmask = NULL;
|
||||||
if (cur->type == XML_ELEMENT_NODE &&
|
unsigned long prefix;
|
||||||
xmlStrEqual(cur->name, BAD_CAST "dhcp")) {
|
int result = -1;
|
||||||
int result = virNetworkDHCPRangeDefParseXML(def, cur);
|
|
||||||
if (result)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
} else if (cur->type == XML_ELEMENT_NODE &&
|
save = ctxt->node;
|
||||||
xmlStrEqual(cur->name, BAD_CAST "tftp")) {
|
ctxt->node = node;
|
||||||
char *root;
|
|
||||||
|
|
||||||
if (!(root = virXMLPropString(cur, "root"))) {
|
/* grab raw data from XML */
|
||||||
cur = cur->next;
|
def->family = virXPathString("string(./@family)", ctxt);
|
||||||
continue;
|
address = virXPathString("string(./@address)", ctxt);
|
||||||
}
|
if (virXPathULong("string(./@prefix)", ctxt, &prefix) < 0)
|
||||||
|
def->prefix = 0;
|
||||||
|
else
|
||||||
|
def->prefix = prefix;
|
||||||
|
|
||||||
def->tftproot = root;
|
netmask = virXPathString("string(./@netmask)", ctxt);
|
||||||
|
|
||||||
|
if (address) {
|
||||||
|
if (virSocketParseAddr(address, &def->address, AF_UNSPEC) < 0) {
|
||||||
|
virNetworkReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("Bad address '%s' in definition of network '%s'"),
|
||||||
|
address, networkName);
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = cur->next;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
/* validate family vs. address */
|
||||||
|
if (def->family == NULL) {
|
||||||
|
if (!(VIR_SOCKET_IS_FAMILY(&def->address, AF_INET) ||
|
||||||
|
VIR_SOCKET_IS_FAMILY(&def->address, AF_UNSPEC))) {
|
||||||
|
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("no family specified for non-IPv4 address address '%s' in network '%s'"),
|
||||||
|
address, networkName);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (STREQ(def->family, "ipv4")) {
|
||||||
|
if (!VIR_SOCKET_IS_FAMILY(&def->address, AF_INET)) {
|
||||||
|
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("family 'ipv4' specified for non-IPv4 address '%s' in network '%s'"),
|
||||||
|
address, networkName);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (STREQ(def->family, "ipv6")) {
|
||||||
|
if (!VIR_SOCKET_IS_FAMILY(&def->address, AF_INET6)) {
|
||||||
|
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("family 'ipv6' specified for non-IPv6 address '%s' in network '%s'"),
|
||||||
|
address, networkName);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
virNetworkReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("Unrecognized family '%s' in definition of network '%s'"),
|
||||||
|
def->family, networkName);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse/validate netmask */
|
||||||
|
if (netmask) {
|
||||||
|
if (address == NULL) {
|
||||||
|
/* netmask is meaningless without an address */
|
||||||
|
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("netmask specified without address in network '%s'"),
|
||||||
|
networkName);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!VIR_SOCKET_IS_FAMILY(&def->address, AF_INET)) {
|
||||||
|
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("netmask not supported for address '%s' in network '%s' (IPv4 only)"),
|
||||||
|
address, networkName);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (def->prefix > 0) {
|
||||||
|
/* can't have both netmask and prefix at the same time */
|
||||||
|
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("network '%s' cannot have both prefix='%u' and a netmask"),
|
||||||
|
networkName, def->prefix);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virSocketParseAddr(netmask, &def->netmask, AF_UNSPEC) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!VIR_SOCKET_IS_FAMILY(&def->netmask, AF_INET)) {
|
||||||
|
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("network '%s' has invalid netmask '%s' for address '%s' (both must be IPv4)"),
|
||||||
|
networkName, netmask, address);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_SOCKET_IS_FAMILY(&def->address, AF_INET)) {
|
||||||
|
/* parse IPv4-related info */
|
||||||
|
cur = node->children;
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (cur->type == XML_ELEMENT_NODE &&
|
||||||
|
xmlStrEqual(cur->name, BAD_CAST "dhcp")) {
|
||||||
|
result = virNetworkDHCPRangeDefParseXML(def, cur);
|
||||||
|
if (result)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
||||||
|
xmlStrEqual(cur->name, BAD_CAST "tftp")) {
|
||||||
|
char *root;
|
||||||
|
|
||||||
|
if (!(root = virXMLPropString(cur, "root"))) {
|
||||||
|
cur = cur->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
def->tftproot = (char *)root;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (result < 0) {
|
||||||
|
virNetworkIpDefClear(def);
|
||||||
|
}
|
||||||
|
VIR_FREE(address);
|
||||||
|
VIR_FREE(netmask);
|
||||||
|
|
||||||
|
ctxt->node = save;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static virNetworkDefPtr
|
static virNetworkDefPtr
|
||||||
@ -424,8 +579,8 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
|
|||||||
{
|
{
|
||||||
virNetworkDefPtr def;
|
virNetworkDefPtr def;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
char *ipAddress;
|
xmlNodePtr *ipNodes = NULL;
|
||||||
char *netmask;
|
int nIps;
|
||||||
|
|
||||||
if (VIR_ALLOC(def) < 0) {
|
if (VIR_ALLOC(def) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
@ -469,44 +624,32 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
|
|||||||
if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0)
|
if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0)
|
||||||
def->delay = 0;
|
def->delay = 0;
|
||||||
|
|
||||||
ipAddress = virXPathString("string(./ip[1]/@address)", ctxt);
|
nIps = virXPathNodeSet("./ip", ctxt, &ipNodes);
|
||||||
if (ipAddress) {
|
if (nIps > 0) {
|
||||||
xmlNodePtr ip;
|
int ii;
|
||||||
|
|
||||||
if (virSocketParseAddr(ipAddress, &def->ipAddress, AF_UNSPEC) < 0)
|
/* allocate array to hold all the addrs */
|
||||||
goto error;
|
if (VIR_ALLOC_N(def->ips, nIps) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
/* XXX someday we want IPv6, so will need to relax this */
|
|
||||||
if (!VIR_SOCKET_IS_FAMILY(&def->ipAddress, AF_INET)) {
|
|
||||||
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
"%s", _("Only IPv4 addresses are supported"));
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
/* parse each addr */
|
||||||
if ((ip = virXPathNode("./ip[1]", ctxt)) &&
|
for (ii = 0; ii < nIps; ii++) {
|
||||||
virNetworkIPParseXML(def, ip) < 0)
|
int ret = virNetworkIPParseXML(def->name, &def->ips[ii],
|
||||||
goto error;
|
ipNodes[ii], ctxt);
|
||||||
}
|
if (ret < 0)
|
||||||
VIR_FREE(ipAddress);
|
goto error;
|
||||||
|
def->nips++;
|
||||||
netmask = virXPathString("string(./ip[1]/@netmask)", ctxt);
|
|
||||||
if (netmask) {
|
|
||||||
|
|
||||||
if (virSocketParseAddr(netmask, &def->netmask, AF_UNSPEC) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* XXX someday we want IPv6, so will need to relax this */
|
|
||||||
if (!VIR_SOCKET_IS_FAMILY(&def->netmask, AF_INET)) {
|
|
||||||
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
"%s", _("Only IPv4 addresses are supported"));
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VIR_FREE(netmask);
|
|
||||||
|
|
||||||
|
|
||||||
/* IPv4 forwarding setup */
|
/* IPv4 forwarding setup */
|
||||||
if (virXPathBoolean("count(./forward) > 0", ctxt)) {
|
if (virXPathBoolean("count(./forward) > 0", ctxt)) {
|
||||||
|
if (def->nips == 0) {
|
||||||
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("Forwarding requested, but no IP address provided"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
tmp = virXPathString("string(./forward[1]/@mode)", ctxt);
|
tmp = virXPathString("string(./forward[1]/@mode)", ctxt);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
if ((def->forwardType = virNetworkForwardTypeFromString(tmp)) < 0) {
|
if ((def->forwardType = virNetworkForwardTypeFromString(tmp)) < 0) {
|
||||||
@ -585,11 +728,101 @@ cleanup:
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virNetworkIpDefFormat(virBufferPtr buf,
|
||||||
|
const virNetworkIpDefPtr def)
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
virBufferAddLit(buf, " <ip");
|
||||||
|
|
||||||
|
if (def->family) {
|
||||||
|
virBufferVSprintf(buf, " family='%s'", def->family);
|
||||||
|
}
|
||||||
|
if (VIR_SOCKET_HAS_ADDR(&def->address)) {
|
||||||
|
char *addr = virSocketFormatAddr(&def->address);
|
||||||
|
if (!addr)
|
||||||
|
goto error;
|
||||||
|
virBufferVSprintf(buf, " address='%s'", addr);
|
||||||
|
VIR_FREE(addr);
|
||||||
|
}
|
||||||
|
if (VIR_SOCKET_HAS_ADDR(&def->netmask)) {
|
||||||
|
char *addr = virSocketFormatAddr(&def->netmask);
|
||||||
|
if (!addr)
|
||||||
|
goto error;
|
||||||
|
virBufferVSprintf(buf, " netmask='%s'", addr);
|
||||||
|
VIR_FREE(addr);
|
||||||
|
}
|
||||||
|
if (def->prefix > 0) {
|
||||||
|
virBufferVSprintf(buf," prefix='%u'", def->prefix);
|
||||||
|
}
|
||||||
|
virBufferAddLit(buf, ">\n");
|
||||||
|
|
||||||
|
if (def->tftproot) {
|
||||||
|
virBufferEscapeString(buf, " <tftp root='%s' />\n",
|
||||||
|
def->tftproot);
|
||||||
|
}
|
||||||
|
if ((def->nranges || def->nhosts)) {
|
||||||
|
int ii;
|
||||||
|
virBufferAddLit(buf, " <dhcp>\n");
|
||||||
|
for (ii = 0 ; ii < def->nranges ; ii++) {
|
||||||
|
char *saddr = virSocketFormatAddr(&def->ranges[ii].start);
|
||||||
|
if (!saddr)
|
||||||
|
goto error;
|
||||||
|
char *eaddr = virSocketFormatAddr(&def->ranges[ii].end);
|
||||||
|
if (!eaddr) {
|
||||||
|
VIR_FREE(saddr);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
virBufferVSprintf(buf, " <range start='%s' end='%s' />\n",
|
||||||
|
saddr, eaddr);
|
||||||
|
VIR_FREE(saddr);
|
||||||
|
VIR_FREE(eaddr);
|
||||||
|
}
|
||||||
|
for (ii = 0 ; ii < def->nhosts ; ii++) {
|
||||||
|
virBufferAddLit(buf, " <host ");
|
||||||
|
if (def->hosts[ii].mac)
|
||||||
|
virBufferVSprintf(buf, "mac='%s' ", def->hosts[ii].mac);
|
||||||
|
if (def->hosts[ii].name)
|
||||||
|
virBufferVSprintf(buf, "name='%s' ", def->hosts[ii].name);
|
||||||
|
if (VIR_SOCKET_HAS_ADDR(&def->hosts[ii].ip)) {
|
||||||
|
char *ipaddr = virSocketFormatAddr(&def->hosts[ii].ip);
|
||||||
|
if (!ipaddr)
|
||||||
|
goto error;
|
||||||
|
virBufferVSprintf(buf, "ip='%s' ", ipaddr);
|
||||||
|
VIR_FREE(ipaddr);
|
||||||
|
}
|
||||||
|
virBufferAddLit(buf, "/>\n");
|
||||||
|
}
|
||||||
|
if (def->bootfile) {
|
||||||
|
virBufferEscapeString(buf, " <bootp file='%s' ",
|
||||||
|
def->bootfile);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAddLit(buf, " </dhcp>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAddLit(buf, " </ip>\n");
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
error:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
char *virNetworkDefFormat(const virNetworkDefPtr def)
|
char *virNetworkDefFormat(const virNetworkDefPtr def)
|
||||||
{
|
{
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
unsigned char *uuid;
|
unsigned char *uuid;
|
||||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
int ii;
|
||||||
|
|
||||||
virBufferAddLit(&buf, "<network>\n");
|
virBufferAddLit(&buf, "<network>\n");
|
||||||
virBufferEscapeString(&buf, " <name>%s</name>\n", def->name);
|
virBufferEscapeString(&buf, " <name>%s</name>\n", def->name);
|
||||||
@ -621,81 +854,9 @@ char *virNetworkDefFormat(const virNetworkDefPtr def)
|
|||||||
if (def->domain)
|
if (def->domain)
|
||||||
virBufferVSprintf(&buf, " <domain name='%s'/>\n", def->domain);
|
virBufferVSprintf(&buf, " <domain name='%s'/>\n", def->domain);
|
||||||
|
|
||||||
if (VIR_SOCKET_HAS_ADDR(&def->ipAddress) ||
|
for (ii = 0; ii < def->nips; ii++) {
|
||||||
VIR_SOCKET_HAS_ADDR(&def->netmask)) {
|
if (virNetworkIpDefFormat(&buf, &def->ips[ii]) < 0)
|
||||||
virBufferAddLit(&buf, " <ip");
|
goto error;
|
||||||
|
|
||||||
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 (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");
|
|
||||||
|
|
||||||
if (def->tftproot) {
|
|
||||||
virBufferEscapeString(&buf, " <tftp root='%s' />\n",
|
|
||||||
def->tftproot);
|
|
||||||
}
|
|
||||||
if ((def->nranges || def->nhosts)) {
|
|
||||||
int i;
|
|
||||||
virBufferAddLit(&buf, " <dhcp>\n");
|
|
||||||
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, " <range start='%s' end='%s' />\n",
|
|
||||||
saddr, eaddr);
|
|
||||||
VIR_FREE(saddr);
|
|
||||||
VIR_FREE(eaddr);
|
|
||||||
}
|
|
||||||
for (i = 0 ; i < def->nhosts ; i++) {
|
|
||||||
virBufferAddLit(&buf, " <host ");
|
|
||||||
if (def->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 (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, " <bootp file='%s' ",
|
|
||||||
def->bootfile);
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
virBufferAddLit(&buf, " </dhcp>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
virBufferAddLit(&buf, " </ip>\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virBufferAddLit(&buf, "</network>\n");
|
virBufferAddLit(&buf, "</network>\n");
|
||||||
|
@ -56,6 +56,32 @@ struct _virNetworkDHCPHostDef {
|
|||||||
virSocketAddr ip;
|
virSocketAddr ip;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _virNetworkIpDef virNetworkIpDef;
|
||||||
|
typedef virNetworkIpDef *virNetworkIpDefPtr;
|
||||||
|
struct _virNetworkIpDef {
|
||||||
|
char *family; /* ipv4 or ipv6 - default is ipv4 */
|
||||||
|
virSocketAddr address; /* Bridge IP address */
|
||||||
|
|
||||||
|
/* One or the other of the following two will be used for a given
|
||||||
|
* IP address, but never both. The parser guarantees this.
|
||||||
|
* Use virNetworkIpDefPrefix/virNetworkIpDefNetmask rather
|
||||||
|
* than accessing the data directly - these utility functions
|
||||||
|
* will convert one into the other as necessary.
|
||||||
|
*/
|
||||||
|
unsigned int prefix; /* ipv6 - only prefix allowed */
|
||||||
|
virSocketAddr netmask; /* ipv4 - either netmask or prefix specified */
|
||||||
|
|
||||||
|
unsigned int nranges; /* Zero or more dhcp ranges */
|
||||||
|
virNetworkDHCPRangeDefPtr ranges;
|
||||||
|
|
||||||
|
unsigned int nhosts; /* Zero or more dhcp hosts */
|
||||||
|
virNetworkDHCPHostDefPtr hosts;
|
||||||
|
|
||||||
|
char *tftproot;
|
||||||
|
char *bootfile;
|
||||||
|
virSocketAddr bootserver;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _virNetworkDef virNetworkDef;
|
typedef struct _virNetworkDef virNetworkDef;
|
||||||
typedef virNetworkDef *virNetworkDefPtr;
|
typedef virNetworkDef *virNetworkDefPtr;
|
||||||
struct _virNetworkDef {
|
struct _virNetworkDef {
|
||||||
@ -70,18 +96,8 @@ struct _virNetworkDef {
|
|||||||
int forwardType; /* One of virNetworkForwardType constants */
|
int forwardType; /* One of virNetworkForwardType constants */
|
||||||
char *forwardDev; /* Destination device for forwarding */
|
char *forwardDev; /* Destination device for forwarding */
|
||||||
|
|
||||||
virSocketAddr ipAddress; /* Bridge IP address */
|
size_t nips;
|
||||||
virSocketAddr netmask;
|
virNetworkIpDefPtr ips; /* ptr to array of IP addresses on this network */
|
||||||
|
|
||||||
unsigned int nranges; /* Zero or more dhcp ranges */
|
|
||||||
virNetworkDHCPRangeDefPtr ranges;
|
|
||||||
|
|
||||||
unsigned int nhosts; /* Zero or more dhcp hosts */
|
|
||||||
virNetworkDHCPHostDefPtr hosts;
|
|
||||||
|
|
||||||
char *tftproot;
|
|
||||||
char *bootfile;
|
|
||||||
virSocketAddr bootserver;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _virNetworkObj virNetworkObj;
|
typedef struct _virNetworkObj virNetworkObj;
|
||||||
@ -133,9 +149,12 @@ virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml,
|
|||||||
|
|
||||||
char *virNetworkDefFormat(const virNetworkDefPtr def);
|
char *virNetworkDefFormat(const virNetworkDefPtr def);
|
||||||
|
|
||||||
int virNetworkDefPrefix(const virNetworkDefPtr def);
|
virNetworkIpDefPtr
|
||||||
int virNetworkDefNetmask(const virNetworkDefPtr def,
|
virNetworkDefGetIpByIndex(const virNetworkDefPtr def,
|
||||||
virSocketAddrPtr netmask);
|
int family, size_t n);
|
||||||
|
int virNetworkIpDefPrefix(const virNetworkIpDefPtr def);
|
||||||
|
int virNetworkIpDefNetmask(const virNetworkIpDefPtr def,
|
||||||
|
virSocketAddrPtr netmask);
|
||||||
|
|
||||||
int virNetworkSaveXML(const char *configDir,
|
int virNetworkSaveXML(const char *configDir,
|
||||||
virNetworkDefPtr def,
|
virNetworkDefPtr def,
|
||||||
|
@ -578,14 +578,15 @@ virNetworkAssignDef;
|
|||||||
virNetworkConfigFile;
|
virNetworkConfigFile;
|
||||||
virNetworkDefFormat;
|
virNetworkDefFormat;
|
||||||
virNetworkDefFree;
|
virNetworkDefFree;
|
||||||
virNetworkDefNetmask;
|
virNetworkDefGetIpByIndex;
|
||||||
virNetworkDefParseFile;
|
virNetworkDefParseFile;
|
||||||
virNetworkDefParseNode;
|
virNetworkDefParseNode;
|
||||||
virNetworkDefParseString;
|
virNetworkDefParseString;
|
||||||
virNetworkDefPrefix;
|
|
||||||
virNetworkDeleteConfig;
|
virNetworkDeleteConfig;
|
||||||
virNetworkFindByName;
|
virNetworkFindByName;
|
||||||
virNetworkFindByUUID;
|
virNetworkFindByUUID;
|
||||||
|
virNetworkIpDefNetmask;
|
||||||
|
virNetworkIpDefPrefix;
|
||||||
virNetworkLoadAllConfigs;
|
virNetworkLoadAllConfigs;
|
||||||
virNetworkObjIsDuplicate;
|
virNetworkObjIsDuplicate;
|
||||||
virNetworkObjListFree;
|
virNetworkObjListFree;
|
||||||
|
@ -145,8 +145,7 @@ networkFindActiveConfigs(struct network_driver *driver) {
|
|||||||
obj->active = 1;
|
obj->active = 1;
|
||||||
|
|
||||||
/* Finally try and read dnsmasq pid if any */
|
/* Finally try and read dnsmasq pid if any */
|
||||||
if ((VIR_SOCKET_HAS_ADDR(&obj->def->ipAddress) ||
|
if (obj->def->ips && (obj->def->nips > 0) &&
|
||||||
obj->def->nranges) &&
|
|
||||||
virFileReadPid(NETWORK_PID_DIR, obj->def->name,
|
virFileReadPid(NETWORK_PID_DIR, obj->def->name,
|
||||||
&obj->dnsmasqPid) == 0) {
|
&obj->dnsmasqPid) == 0) {
|
||||||
|
|
||||||
@ -366,7 +365,7 @@ networkShutdown(void) {
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
networkSaveDnsmasqHostsfile(virNetworkObjPtr network,
|
networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef,
|
||||||
dnsmasqContext *dctx,
|
dnsmasqContext *dctx,
|
||||||
bool force)
|
bool force)
|
||||||
{
|
{
|
||||||
@ -375,8 +374,8 @@ networkSaveDnsmasqHostsfile(virNetworkObjPtr network,
|
|||||||
if (! force && virFileExists(dctx->hostsfile->path))
|
if (! force && virFileExists(dctx->hostsfile->path))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = 0 ; i < network->def->nhosts ; i++) {
|
for (i = 0; i < ipdef->nhosts; i++) {
|
||||||
virNetworkDHCPHostDefPtr host = &(network->def->hosts[i]);
|
virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
|
||||||
if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip))
|
if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip))
|
||||||
dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name);
|
dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name);
|
||||||
}
|
}
|
||||||
@ -390,13 +389,14 @@ networkSaveDnsmasqHostsfile(virNetworkObjPtr network,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
networkBuildDnsmasqArgv(virNetworkObjPtr network,
|
networkBuildDnsmasqArgv(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef,
|
||||||
const char *pidfile,
|
const char *pidfile,
|
||||||
virCommandPtr cmd) {
|
virCommandPtr cmd) {
|
||||||
int r, ret = -1;
|
int r, ret = -1;
|
||||||
int nbleases = 0;
|
int nbleases = 0;
|
||||||
char *bridgeaddr;
|
char *bridgeaddr;
|
||||||
|
|
||||||
if (!(bridgeaddr = virSocketFormatAddr(&network->def->ipAddress)))
|
if (!(bridgeaddr = virSocketFormatAddr(&ipdef->address)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
/*
|
/*
|
||||||
* NB, be careful about syntax for dnsmasq options in long format.
|
* NB, be careful about syntax for dnsmasq options in long format.
|
||||||
@ -438,18 +438,18 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
|
|||||||
* clearly not practical
|
* clearly not practical
|
||||||
*
|
*
|
||||||
* virCommandAddArg(cmd, "--interface");
|
* virCommandAddArg(cmd, "--interface");
|
||||||
* virCommandAddArg(cmd, network->def->bridge);
|
* virCommandAddArg(cmd, ipdef->bridge);
|
||||||
*/
|
*/
|
||||||
virCommandAddArgList(cmd,
|
virCommandAddArgList(cmd,
|
||||||
"--listen-address", bridgeaddr,
|
"--listen-address", bridgeaddr,
|
||||||
"--except-interface", "lo",
|
"--except-interface", "lo",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
for (r = 0 ; r < network->def->nranges ; r++) {
|
for (r = 0 ; r < ipdef->nranges ; r++) {
|
||||||
char *saddr = virSocketFormatAddr(&network->def->ranges[r].start);
|
char *saddr = virSocketFormatAddr(&ipdef->ranges[r].start);
|
||||||
if (!saddr)
|
if (!saddr)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
char *eaddr = virSocketFormatAddr(&network->def->ranges[r].end);
|
char *eaddr = virSocketFormatAddr(&ipdef->ranges[r].end);
|
||||||
if (!eaddr) {
|
if (!eaddr) {
|
||||||
VIR_FREE(saddr);
|
VIR_FREE(saddr);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -458,8 +458,8 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
|
|||||||
virCommandAddArgFormat(cmd, "%s,%s", saddr, eaddr);
|
virCommandAddArgFormat(cmd, "%s,%s", saddr, eaddr);
|
||||||
VIR_FREE(saddr);
|
VIR_FREE(saddr);
|
||||||
VIR_FREE(eaddr);
|
VIR_FREE(eaddr);
|
||||||
nbleases += virSocketGetRange(&network->def->ranges[r].start,
|
nbleases += virSocketGetRange(&ipdef->ranges[r].start,
|
||||||
&network->def->ranges[r].end);
|
&ipdef->ranges[r].end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -467,19 +467,19 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
|
|||||||
* we have to add a special --dhcp-range option to enable the service in
|
* we have to add a special --dhcp-range option to enable the service in
|
||||||
* dnsmasq.
|
* dnsmasq.
|
||||||
*/
|
*/
|
||||||
if (!network->def->nranges && network->def->nhosts) {
|
if (!ipdef->nranges && ipdef->nhosts) {
|
||||||
virCommandAddArg(cmd, "--dhcp-range");
|
virCommandAddArg(cmd, "--dhcp-range");
|
||||||
virCommandAddArgFormat(cmd, "%s,static", bridgeaddr);
|
virCommandAddArgFormat(cmd, "%s,static", bridgeaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network->def->nranges > 0) {
|
if (ipdef->nranges > 0) {
|
||||||
virCommandAddArgFormat(cmd, "--dhcp-lease-max=%d", nbleases);
|
virCommandAddArgFormat(cmd, "--dhcp-lease-max=%d", nbleases);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network->def->nranges || network->def->nhosts)
|
if (ipdef->nranges || ipdef->nhosts)
|
||||||
virCommandAddArg(cmd, "--dhcp-no-override");
|
virCommandAddArg(cmd, "--dhcp-no-override");
|
||||||
|
|
||||||
if (network->def->nhosts > 0) {
|
if (ipdef->nhosts > 0) {
|
||||||
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name,
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name,
|
||||||
DNSMASQ_STATE_DIR);
|
DNSMASQ_STATE_DIR);
|
||||||
if (dctx == NULL) {
|
if (dctx == NULL) {
|
||||||
@ -487,31 +487,30 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkSaveDnsmasqHostsfile(network, dctx, false) < 0) {
|
if (networkSaveDnsmasqHostsfile(ipdef, dctx, false) < 0) {
|
||||||
virCommandAddArgPair(cmd, "--dhcp-hostsfile",
|
virCommandAddArgPair(cmd, "--dhcp-hostsfile",
|
||||||
dctx->hostsfile->path);
|
dctx->hostsfile->path);
|
||||||
}
|
}
|
||||||
dnsmasqContextFree(dctx);
|
dnsmasqContextFree(dctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network->def->tftproot) {
|
if (ipdef->tftproot) {
|
||||||
virCommandAddArgList(cmd, "--enable-tftp",
|
virCommandAddArgList(cmd, "--enable-tftp",
|
||||||
"--tftp-root", network->def->tftproot,
|
"--tftp-root", ipdef->tftproot,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
if (network->def->bootfile) {
|
if (ipdef->bootfile) {
|
||||||
|
|
||||||
virCommandAddArg(cmd, "--dhcp-boot");
|
virCommandAddArg(cmd, "--dhcp-boot");
|
||||||
if (VIR_SOCKET_HAS_ADDR(&network->def->bootserver)) {
|
if (VIR_SOCKET_HAS_ADDR(&ipdef->bootserver)) {
|
||||||
char *bootserver = virSocketFormatAddr(&network->def->bootserver);
|
char *bootserver = virSocketFormatAddr(&ipdef->bootserver);
|
||||||
|
|
||||||
if (!bootserver)
|
if (!bootserver)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
virCommandAddArgFormat(cmd, "%s%s%s",
|
virCommandAddArgFormat(cmd, "%s%s%s",
|
||||||
network->def->bootfile, ",,", bootserver);
|
ipdef->bootfile, ",,", bootserver);
|
||||||
VIR_FREE(bootserver);
|
VIR_FREE(bootserver);
|
||||||
} else {
|
} else {
|
||||||
virCommandAddArg(cmd, network->def->bootfile);
|
virCommandAddArg(cmd, ipdef->bootfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,9 +520,9 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dhcpStartDhcpDaemon(virNetworkObjPtr network)
|
dhcpStartDhcpDaemon(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
{
|
{
|
||||||
virCommandPtr cmd = NULL;
|
virCommandPtr cmd = NULL;
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
@ -531,7 +530,7 @@ dhcpStartDhcpDaemon(virNetworkObjPtr network)
|
|||||||
|
|
||||||
network->dnsmasqPid = -1;
|
network->dnsmasqPid = -1;
|
||||||
|
|
||||||
if (!VIR_SOCKET_IS_FAMILY(&network->def->ipAddress, AF_INET)) {
|
if (!VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("cannot start dhcp daemon without IPv4 address for server"));
|
"%s", _("cannot start dhcp daemon without IPv4 address for server"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -556,7 +555,7 @@ dhcpStartDhcpDaemon(virNetworkObjPtr network)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd = virCommandNew(DNSMASQ);
|
cmd = virCommandNew(DNSMASQ);
|
||||||
if (networkBuildDnsmasqArgv(network, pidfile, cmd) < 0) {
|
if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,8 +583,10 @@ cleanup:
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
||||||
virNetworkObjPtr network) {
|
virNetworkObjPtr network,
|
||||||
int prefix = virNetworkDefPrefix(network->def);
|
virNetworkIpDefPtr ipdef)
|
||||||
|
{
|
||||||
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
|
||||||
if (prefix < 0) {
|
if (prefix < 0) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -596,7 +597,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
/* allow forwarding packets from the bridge interface */
|
/* allow forwarding packets from the bridge interface */
|
||||||
if (iptablesAddForwardAllowOut(driver->iptables,
|
if (iptablesAddForwardAllowOut(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev) < 0) {
|
network->def->forwardDev) < 0) {
|
||||||
@ -608,7 +609,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
/* allow forwarding packets to the bridge interface if they are part of an existing connection */
|
/* allow forwarding packets to the bridge interface if they are part of an existing connection */
|
||||||
if (iptablesAddForwardAllowRelatedIn(driver->iptables,
|
if (iptablesAddForwardAllowRelatedIn(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev) < 0) {
|
network->def->forwardDev) < 0) {
|
||||||
@ -643,7 +644,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
/* First the generic masquerade rule for other protocols */
|
/* First the generic masquerade rule for other protocols */
|
||||||
if (iptablesAddForwardMasquerade(driver->iptables,
|
if (iptablesAddForwardMasquerade(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->forwardDev,
|
network->def->forwardDev,
|
||||||
NULL) < 0) {
|
NULL) < 0) {
|
||||||
@ -655,7 +656,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
/* UDP with a source port restriction */
|
/* UDP with a source port restriction */
|
||||||
if (iptablesAddForwardMasquerade(driver->iptables,
|
if (iptablesAddForwardMasquerade(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->forwardDev,
|
network->def->forwardDev,
|
||||||
"udp") < 0) {
|
"udp") < 0) {
|
||||||
@ -667,7 +668,7 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
/* TCP with a source port restriction */
|
/* TCP with a source port restriction */
|
||||||
if (iptablesAddForwardMasquerade(driver->iptables,
|
if (iptablesAddForwardMasquerade(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->forwardDev,
|
network->def->forwardDev,
|
||||||
"tcp") < 0) {
|
"tcp") < 0) {
|
||||||
@ -681,25 +682,25 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
masqerr5:
|
masqerr5:
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->forwardDev,
|
network->def->forwardDev,
|
||||||
"udp");
|
"udp");
|
||||||
masqerr4:
|
masqerr4:
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->forwardDev,
|
network->def->forwardDev,
|
||||||
NULL);
|
NULL);
|
||||||
masqerr3:
|
masqerr3:
|
||||||
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev);
|
network->def->forwardDev);
|
||||||
masqerr2:
|
masqerr2:
|
||||||
iptablesRemoveForwardAllowOut(driver->iptables,
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev);
|
network->def->forwardDev);
|
||||||
@ -709,8 +710,9 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
networkAddRoutingIptablesRules(struct network_driver *driver,
|
networkAddRoutingIptablesRules(struct network_driver *driver,
|
||||||
virNetworkObjPtr network) {
|
virNetworkObjPtr network,
|
||||||
int prefix = virNetworkDefPrefix(network->def);
|
virNetworkIpDefPtr ipdef) {
|
||||||
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
|
||||||
if (prefix < 0) {
|
if (prefix < 0) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -721,7 +723,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
/* allow routing packets from the bridge interface */
|
/* allow routing packets from the bridge interface */
|
||||||
if (iptablesAddForwardAllowOut(driver->iptables,
|
if (iptablesAddForwardAllowOut(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev) < 0) {
|
network->def->forwardDev) < 0) {
|
||||||
@ -733,7 +735,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
/* allow routing packets to the bridge interface */
|
/* allow routing packets to the bridge interface */
|
||||||
if (iptablesAddForwardAllowIn(driver->iptables,
|
if (iptablesAddForwardAllowIn(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev) < 0) {
|
network->def->forwardDev) < 0) {
|
||||||
@ -748,7 +750,7 @@ networkAddRoutingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
routeerr2:
|
routeerr2:
|
||||||
iptablesRemoveForwardAllowOut(driver->iptables,
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev);
|
network->def->forwardDev);
|
||||||
@ -758,7 +760,8 @@ networkAddRoutingIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
networkAddIptablesRules(struct network_driver *driver,
|
networkAddIptablesRules(struct network_driver *driver,
|
||||||
virNetworkObjPtr network) {
|
virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef) {
|
||||||
|
|
||||||
/* allow DHCP requests through to dnsmasq */
|
/* allow DHCP requests through to dnsmasq */
|
||||||
if (iptablesAddTcpInput(driver->iptables, network->def->bridge, 67) < 0) {
|
if (iptablesAddTcpInput(driver->iptables, network->def->bridge, 67) < 0) {
|
||||||
@ -791,7 +794,7 @@ networkAddIptablesRules(struct network_driver *driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* allow TFTP requests through to dnsmasq */
|
/* allow TFTP requests through to dnsmasq */
|
||||||
if (network->def->tftproot &&
|
if (ipdef && ipdef->tftproot &&
|
||||||
iptablesAddUdpInput(driver->iptables, network->def->bridge, 69) < 0) {
|
iptablesAddUdpInput(driver->iptables, network->def->bridge, 69) < 0) {
|
||||||
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
||||||
_("failed to add iptables rule to allow TFTP requests from '%s'"),
|
_("failed to add iptables rule to allow TFTP requests from '%s'"),
|
||||||
@ -824,29 +827,30 @@ networkAddIptablesRules(struct network_driver *driver,
|
|||||||
goto err7;
|
goto err7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ipdef) {
|
||||||
|
/* If masquerading is enabled, set up the rules*/
|
||||||
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT &&
|
||||||
|
networkAddMasqueradingIptablesRules(driver, network, ipdef) < 0)
|
||||||
|
goto err8;
|
||||||
|
/* else if routing is enabled, set up the rules*/
|
||||||
|
else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE &&
|
||||||
|
networkAddRoutingIptablesRules(driver, network, ipdef) < 0)
|
||||||
|
goto err8;
|
||||||
|
|
||||||
/* If masquerading is enabled, set up the rules*/
|
/* If we are doing local DHCP service on this network, attempt to
|
||||||
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT &&
|
* add a rule that will fixup the checksum of DHCP response
|
||||||
networkAddMasqueradingIptablesRules(driver, network) < 0)
|
* packets back to the guests (but report failure without
|
||||||
goto err8;
|
* aborting, since not all iptables implementations support it).
|
||||||
/* else if routing is enabled, set up the rules*/
|
*/
|
||||||
else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE &&
|
|
||||||
networkAddRoutingIptablesRules(driver, network) < 0)
|
|
||||||
goto err8;
|
|
||||||
|
|
||||||
/* If we are doing local DHCP service on this network, attempt to
|
if (ipdef && (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET) ||
|
||||||
* add a rule that will fixup the checksum of DHCP response
|
ipdef->nranges) &&
|
||||||
* packets back to the guests (but report failure without
|
(iptablesAddOutputFixUdpChecksum(driver->iptables,
|
||||||
* aborting, since not all iptables implementations support it).
|
network->def->bridge, 68) < 0)) {
|
||||||
*/
|
VIR_WARN("Could not add rule to fixup DHCP response checksums "
|
||||||
|
"on network '%s'.", network->def->name);
|
||||||
if ((VIR_SOCKET_HAS_ADDR(&network->def->ipAddress) ||
|
VIR_WARN0("May need to update iptables package & kernel to support CHECKSUM rule.");
|
||||||
network->def->nranges) &&
|
}
|
||||||
(iptablesAddOutputFixUdpChecksum(driver->iptables,
|
|
||||||
network->def->bridge, 68) < 0)) {
|
|
||||||
VIR_WARN("Could not add rule to fixup DHCP response checksums "
|
|
||||||
"on network '%s'.", network->def->name);
|
|
||||||
VIR_WARN0("May need to update iptables package & kernel to support CHECKSUM rule.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -861,7 +865,7 @@ networkAddIptablesRules(struct network_driver *driver,
|
|||||||
iptablesRemoveForwardRejectOut(driver->iptables,
|
iptablesRemoveForwardRejectOut(driver->iptables,
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
err5:
|
err5:
|
||||||
if (network->def->tftproot) {
|
if (ipdef && ipdef->tftproot) {
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
||||||
}
|
}
|
||||||
err4tftp:
|
err4tftp:
|
||||||
@ -878,14 +882,16 @@ networkAddIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
networkRemoveIptablesRules(struct network_driver *driver,
|
networkRemoveIptablesRules(struct network_driver *driver,
|
||||||
virNetworkObjPtr network) {
|
virNetworkObjPtr network,
|
||||||
if (VIR_SOCKET_HAS_ADDR(&network->def->ipAddress) ||
|
virNetworkIpDefPtr ipdef) {
|
||||||
network->def->nranges) {
|
|
||||||
|
if (ipdef && (VIR_SOCKET_HAS_ADDR(&ipdef->address) ||
|
||||||
|
ipdef->nranges)) {
|
||||||
iptablesRemoveOutputFixUdpChecksum(driver->iptables,
|
iptablesRemoveOutputFixUdpChecksum(driver->iptables,
|
||||||
network->def->bridge, 68);
|
network->def->bridge, 68);
|
||||||
}
|
}
|
||||||
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
|
if (ipdef && network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
|
||||||
int prefix = virNetworkDefPrefix(network->def);
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
||||||
|
|
||||||
if (prefix < 0) {
|
if (prefix < 0) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -896,34 +902,35 @@ networkRemoveIptablesRules(struct network_driver *driver,
|
|||||||
|
|
||||||
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->forwardDev,
|
network->def->forwardDev,
|
||||||
"tcp");
|
"tcp");
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->forwardDev,
|
network->def->forwardDev,
|
||||||
"udp");
|
"udp");
|
||||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->forwardDev,
|
network->def->forwardDev,
|
||||||
NULL);
|
NULL);
|
||||||
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev);
|
network->def->forwardDev);
|
||||||
} else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE)
|
} else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
|
||||||
iptablesRemoveForwardAllowIn(driver->iptables,
|
iptablesRemoveForwardAllowIn(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev);
|
network->def->forwardDev);
|
||||||
|
}
|
||||||
|
|
||||||
iptablesRemoveForwardAllowOut(driver->iptables,
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
||||||
&network->def->ipAddress,
|
&ipdef->address,
|
||||||
prefix,
|
prefix,
|
||||||
network->def->bridge,
|
network->def->bridge,
|
||||||
network->def->forwardDev);
|
network->def->forwardDev);
|
||||||
@ -932,7 +939,7 @@ error:
|
|||||||
iptablesRemoveForwardAllowCross(driver->iptables, network->def->bridge);
|
iptablesRemoveForwardAllowCross(driver->iptables, network->def->bridge);
|
||||||
iptablesRemoveForwardRejectIn(driver->iptables, network->def->bridge);
|
iptablesRemoveForwardRejectIn(driver->iptables, network->def->bridge);
|
||||||
iptablesRemoveForwardRejectOut(driver->iptables, network->def->bridge);
|
iptablesRemoveForwardRejectOut(driver->iptables, network->def->bridge);
|
||||||
if (network->def->tftproot)
|
if (ipdef && ipdef->tftproot)
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
||||||
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
|
||||||
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
|
||||||
@ -951,10 +958,18 @@ networkReloadIptablesRules(struct network_driver *driver)
|
|||||||
virNetworkObjLock(driver->networks.objs[i]);
|
virNetworkObjLock(driver->networks.objs[i]);
|
||||||
|
|
||||||
if (virNetworkObjIsActive(driver->networks.objs[i])) {
|
if (virNetworkObjIsActive(driver->networks.objs[i])) {
|
||||||
networkRemoveIptablesRules(driver, driver->networks.objs[i]);
|
virNetworkIpDefPtr ipv4def;
|
||||||
if (networkAddIptablesRules(driver, driver->networks.objs[i]) < 0) {
|
|
||||||
/* failed to add but already logged */
|
/* Find the one allowed IPv4 ip address in the definition */
|
||||||
}
|
/* Even if none is found, we still call the functions below */
|
||||||
|
ipv4def = virNetworkDefGetIpByIndex(driver->networks.objs[i]->def,
|
||||||
|
AF_INET, 0);
|
||||||
|
networkRemoveIptablesRules(driver, driver->networks.objs[i],
|
||||||
|
ipv4def);
|
||||||
|
if (networkAddIptablesRules(driver, driver->networks.objs[i],
|
||||||
|
ipv4def) < 0) {
|
||||||
|
/* failed to add but already logged */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virNetworkObjUnlock(driver->networks.objs[i]);
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
||||||
@ -1028,7 +1043,8 @@ cleanup:
|
|||||||
* other scenarios where we can ruin host network connectivity.
|
* other scenarios where we can ruin host network connectivity.
|
||||||
* XXX: Using a proper library is preferred over parsing /proc
|
* XXX: Using a proper library is preferred over parsing /proc
|
||||||
*/
|
*/
|
||||||
static int networkCheckRouteCollision(virNetworkObjPtr network)
|
static int networkCheckRouteCollision(virNetworkObjPtr network,
|
||||||
|
virNetworkIpDefPtr ipdef)
|
||||||
{
|
{
|
||||||
int ret = -1, len;
|
int ret = -1, len;
|
||||||
unsigned int net_dest;
|
unsigned int net_dest;
|
||||||
@ -1036,18 +1052,18 @@ static int networkCheckRouteCollision(virNetworkObjPtr network)
|
|||||||
char *cur, *buf = NULL;
|
char *cur, *buf = NULL;
|
||||||
enum {MAX_ROUTE_SIZE = 1024*64};
|
enum {MAX_ROUTE_SIZE = 1024*64};
|
||||||
|
|
||||||
if (!VIR_SOCKET_IS_FAMILY(&network->def->ipAddress, AF_INET)) {
|
if (!VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
|
||||||
/* Only support collision check for IPv4 */
|
/* Only support collision check for IPv4 */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virNetworkDefNetmask(network->def, &netmask) < 0) {
|
if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Failed to get netmask of '%s'"),
|
_("Failed to get netmask of '%s'"),
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
net_dest = (network->def->ipAddress.data.inet4.sin_addr.s_addr &
|
net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
|
||||||
netmask.data.inet4.sin_addr.s_addr);
|
netmask.data.inet4.sin_addr.s_addr);
|
||||||
|
|
||||||
/* Read whole routing table into memory */
|
/* Read whole routing table into memory */
|
||||||
@ -1121,6 +1137,7 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
virErrorPtr save_err;
|
virErrorPtr save_err;
|
||||||
|
virNetworkIpDefPtr ipv4def;
|
||||||
|
|
||||||
if (virNetworkObjIsActive(network)) {
|
if (virNetworkObjIsActive(network)) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -1128,8 +1145,11 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* find the one allowed IPv4 ip address in the definition */
|
||||||
|
ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, 0);
|
||||||
|
|
||||||
/* Check to see if network collides with an existing route */
|
/* Check to see if network collides with an existing route */
|
||||||
if (networkCheckRouteCollision(network) < 0)
|
if (ipv4def && networkCheckRouteCollision(network, ipv4def) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
|
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
|
||||||
@ -1158,8 +1178,8 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
goto err_delbr;
|
goto err_delbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VIR_SOCKET_HAS_ADDR(&network->def->ipAddress)) {
|
if (ipv4def) {
|
||||||
int prefix = virNetworkDefPrefix(network->def);
|
int prefix = virNetworkIpDefPrefix(ipv4def);
|
||||||
|
|
||||||
if (prefix < 0) {
|
if (prefix < 0) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -1169,7 +1189,7 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((err = brAddInetAddress(driver->brctl, network->def->bridge,
|
if ((err = brAddInetAddress(driver->brctl, network->def->bridge,
|
||||||
&network->def->ipAddress, prefix))) {
|
&ipv4def->address, prefix))) {
|
||||||
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot set IP address on bridge '%s'"),
|
_("cannot set IP address on bridge '%s'"),
|
||||||
network->def->bridge);
|
network->def->bridge);
|
||||||
@ -1184,7 +1204,7 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
goto err_delbr;
|
goto err_delbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkAddIptablesRules(driver, network) < 0)
|
if (ipv4def && networkAddIptablesRules(driver, network, ipv4def) < 0)
|
||||||
goto err_delbr1;
|
goto err_delbr1;
|
||||||
|
|
||||||
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
|
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
|
||||||
@ -1194,12 +1214,13 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
goto err_delbr2;
|
goto err_delbr2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((VIR_SOCKET_HAS_ADDR(&network->def->ipAddress) ||
|
/*
|
||||||
network->def->nranges) &&
|
* Start the dhcp daemon for the 1st (and only supported) ipv4
|
||||||
dhcpStartDhcpDaemon(network) < 0)
|
* address.
|
||||||
|
*/
|
||||||
|
if (ipv4def && dhcpStartDhcpDaemon(network, ipv4def) < 0)
|
||||||
goto err_delbr2;
|
goto err_delbr2;
|
||||||
|
|
||||||
|
|
||||||
/* Persist the live configuration now we have bridge info */
|
/* Persist the live configuration now we have bridge info */
|
||||||
if (virNetworkSaveConfig(NETWORK_STATE_DIR, network->def) < 0) {
|
if (virNetworkSaveConfig(NETWORK_STATE_DIR, network->def) < 0) {
|
||||||
goto err_kill;
|
goto err_kill;
|
||||||
@ -1217,7 +1238,8 @@ static int networkStartNetworkDaemon(struct network_driver *driver,
|
|||||||
|
|
||||||
err_delbr2:
|
err_delbr2:
|
||||||
save_err = virSaveLastError();
|
save_err = virSaveLastError();
|
||||||
networkRemoveIptablesRules(driver, network);
|
if (ipv4def)
|
||||||
|
networkRemoveIptablesRules(driver, network, ipv4def);
|
||||||
if (save_err) {
|
if (save_err) {
|
||||||
virSetError(save_err);
|
virSetError(save_err);
|
||||||
virFreeError(save_err);
|
virFreeError(save_err);
|
||||||
@ -1246,6 +1268,7 @@ static int networkShutdownNetworkDaemon(struct network_driver *driver,
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
char *stateFile;
|
char *stateFile;
|
||||||
|
virNetworkIpDefPtr ipv4def;
|
||||||
|
|
||||||
VIR_INFO(_("Shutting down network '%s'"), network->def->name);
|
VIR_INFO(_("Shutting down network '%s'"), network->def->name);
|
||||||
|
|
||||||
@ -1262,7 +1285,10 @@ static int networkShutdownNetworkDaemon(struct network_driver *driver,
|
|||||||
if (network->dnsmasqPid > 0)
|
if (network->dnsmasqPid > 0)
|
||||||
kill(network->dnsmasqPid, SIGTERM);
|
kill(network->dnsmasqPid, SIGTERM);
|
||||||
|
|
||||||
networkRemoveIptablesRules(driver, network);
|
/* find the one allowed IPv4 ip address in the definition */
|
||||||
|
ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, 0);
|
||||||
|
if (ipv4def)
|
||||||
|
networkRemoveIptablesRules(driver, network, ipv4def);
|
||||||
|
|
||||||
char ebuf[1024];
|
char ebuf[1024];
|
||||||
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
|
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
|
||||||
@ -1526,6 +1552,7 @@ cleanup:
|
|||||||
|
|
||||||
static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
|
static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
|
||||||
struct network_driver *driver = conn->networkPrivateData;
|
struct network_driver *driver = conn->networkPrivateData;
|
||||||
|
virNetworkIpDefPtr ipv4def;
|
||||||
virNetworkDefPtr def;
|
virNetworkDefPtr def;
|
||||||
virNetworkObjPtr network = NULL;
|
virNetworkObjPtr network = NULL;
|
||||||
virNetworkPtr ret = NULL;
|
virNetworkPtr ret = NULL;
|
||||||
@ -1556,12 +1583,15 @@ static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network->def->nhosts > 0) {
|
/* we only support dhcp on one IPv4 address per defined network */
|
||||||
|
ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, 0);
|
||||||
|
|
||||||
|
if (ipv4def && ipv4def->nhosts > 0) {
|
||||||
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
||||||
if (dctx == NULL)
|
if (dctx == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
networkSaveDnsmasqHostsfile(network, dctx, true);
|
networkSaveDnsmasqHostsfile(ipv4def, dctx, true);
|
||||||
dnsmasqContextFree(dctx);
|
dnsmasqContextFree(dctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1577,7 +1607,8 @@ cleanup:
|
|||||||
|
|
||||||
static int networkUndefine(virNetworkPtr net) {
|
static int networkUndefine(virNetworkPtr net) {
|
||||||
struct network_driver *driver = net->conn->networkPrivateData;
|
struct network_driver *driver = net->conn->networkPrivateData;
|
||||||
virNetworkObjPtr network = NULL;
|
virNetworkObjPtr network;
|
||||||
|
virNetworkIpDefPtr ipv4def;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
networkDriverLock(driver);
|
networkDriverLock(driver);
|
||||||
@ -1600,7 +1631,10 @@ static int networkUndefine(virNetworkPtr net) {
|
|||||||
network) < 0)
|
network) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (network->def->nhosts > 0) {
|
/* find the one allowed IPv4 ip address in the definition */
|
||||||
|
ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, 0);
|
||||||
|
|
||||||
|
if (ipv4def && ipv4def->nhosts > 0) {
|
||||||
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
||||||
if (dctx == NULL)
|
if (dctx == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -7038,9 +7038,23 @@ static virNetworkPtr vboxNetworkDefineCreateXML(virConnectPtr conn, const char *
|
|||||||
IHostNetworkInterface *networkInterface = NULL;
|
IHostNetworkInterface *networkInterface = NULL;
|
||||||
|
|
||||||
virNetworkDefPtr def = virNetworkDefParseString(xml);
|
virNetworkDefPtr def = virNetworkDefParseString(xml);
|
||||||
|
virNetworkIpDefPtr ipdef;
|
||||||
|
virSocketAddr netmask;
|
||||||
|
|
||||||
if ( (!def)
|
if ( (!def)
|
||||||
|| (def->forwardType != VIR_NETWORK_FORWARD_NONE))
|
|| (def->forwardType != VIR_NETWORK_FORWARD_NONE)
|
||||||
|
|| (def->nips == 0 || !def->ips))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Look for the first IPv4 IP address definition and use that.
|
||||||
|
* If there weren't any IPv4 addresses, ignore the network (since it's
|
||||||
|
* required below to have an IPv4 address)
|
||||||
|
*/
|
||||||
|
ipdef = virNetworkDefGetIpByIndex(def, AF_INET, 0);
|
||||||
|
if (!ipdef)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virNetworkIpDefNetmask(ipdef, &netmask) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* the current limitation of hostonly network is that you can't
|
/* the current limitation of hostonly network is that you can't
|
||||||
@ -7096,9 +7110,9 @@ static virNetworkPtr vboxNetworkDefineCreateXML(virConnectPtr conn, const char *
|
|||||||
/* Currently support only one dhcp server per network
|
/* Currently support only one dhcp server per network
|
||||||
* with contigious address space from start to end
|
* with contigious address space from start to end
|
||||||
*/
|
*/
|
||||||
if ((def->nranges >= 1) &&
|
if ((ipdef->nranges >= 1) &&
|
||||||
VIR_SOCKET_HAS_ADDR(&def->ranges[0].start) &&
|
VIR_SOCKET_HAS_ADDR(&ipdef->ranges[0].start) &&
|
||||||
VIR_SOCKET_HAS_ADDR(&def->ranges[0].end)) {
|
VIR_SOCKET_HAS_ADDR(&ipdef->ranges[0].end)) {
|
||||||
IDHCPServer *dhcpServer = NULL;
|
IDHCPServer *dhcpServer = NULL;
|
||||||
|
|
||||||
data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj,
|
data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj,
|
||||||
@ -7118,10 +7132,10 @@ static virNetworkPtr vboxNetworkDefineCreateXML(virConnectPtr conn, const char *
|
|||||||
PRUnichar *toIPAddressUtf16 = NULL;
|
PRUnichar *toIPAddressUtf16 = NULL;
|
||||||
PRUnichar *trunkTypeUtf16 = NULL;
|
PRUnichar *trunkTypeUtf16 = NULL;
|
||||||
|
|
||||||
ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &def->ipAddress);
|
ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->address);
|
||||||
networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &def->netmask);
|
networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &netmask);
|
||||||
fromIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &def->ranges[0].start);
|
fromIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->ranges[0].start);
|
||||||
toIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &def->ranges[0].end);
|
toIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->ranges[0].end);
|
||||||
|
|
||||||
if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL ||
|
if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL ||
|
||||||
fromIPAddressUtf16 == NULL || toIPAddressUtf16 == NULL) {
|
fromIPAddressUtf16 == NULL || toIPAddressUtf16 == NULL) {
|
||||||
@ -7158,13 +7172,13 @@ static virNetworkPtr vboxNetworkDefineCreateXML(virConnectPtr conn, const char *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((def->nhosts >= 1) &&
|
if ((ipdef->nhosts >= 1) &&
|
||||||
VIR_SOCKET_HAS_ADDR(&def->hosts[0].ip)) {
|
VIR_SOCKET_HAS_ADDR(&ipdef->hosts[0].ip)) {
|
||||||
PRUnichar *ipAddressUtf16 = NULL;
|
PRUnichar *ipAddressUtf16 = NULL;
|
||||||
PRUnichar *networkMaskUtf16 = NULL;
|
PRUnichar *networkMaskUtf16 = NULL;
|
||||||
|
|
||||||
ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &def->hosts[0].ip);
|
ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->hosts[0].ip);
|
||||||
networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &def->netmask);
|
networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &netmask);
|
||||||
|
|
||||||
if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL) {
|
if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL) {
|
||||||
VBOX_UTF16_FREE(ipAddressUtf16);
|
VBOX_UTF16_FREE(ipAddressUtf16);
|
||||||
@ -7385,12 +7399,19 @@ static int vboxNetworkDestroy(virNetworkPtr network) {
|
|||||||
static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
|
static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
|
||||||
VBOX_OBJECT_HOST_CHECK(network->conn, char *, NULL);
|
VBOX_OBJECT_HOST_CHECK(network->conn, char *, NULL);
|
||||||
virNetworkDefPtr def = NULL;
|
virNetworkDefPtr def = NULL;
|
||||||
|
virNetworkIpDefPtr ipdef = NULL;
|
||||||
char *networkNameUtf8 = NULL;
|
char *networkNameUtf8 = NULL;
|
||||||
|
|
||||||
if (VIR_ALLOC(def) < 0) {
|
if (VIR_ALLOC(def) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
if (VIR_ALLOC(ipdef) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
def->ips = ipdef;
|
||||||
|
def->nips = 1;
|
||||||
|
|
||||||
if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0) {
|
if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
@ -7427,8 +7448,8 @@ static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSE
|
|||||||
networkNameUtf16,
|
networkNameUtf16,
|
||||||
&dhcpServer);
|
&dhcpServer);
|
||||||
if (dhcpServer) {
|
if (dhcpServer) {
|
||||||
def->nranges = 1;
|
ipdef->nranges = 1;
|
||||||
if (VIR_ALLOC_N(def->ranges, def->nranges) >=0 ) {
|
if (VIR_ALLOC_N(ipdef->ranges, ipdef->nranges) >=0 ) {
|
||||||
PRUnichar *ipAddressUtf16 = NULL;
|
PRUnichar *ipAddressUtf16 = NULL;
|
||||||
PRUnichar *networkMaskUtf16 = NULL;
|
PRUnichar *networkMaskUtf16 = NULL;
|
||||||
PRUnichar *fromIPAddressUtf16 = NULL;
|
PRUnichar *fromIPAddressUtf16 = NULL;
|
||||||
@ -7443,13 +7464,13 @@ static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSE
|
|||||||
* with contigious address space from start to end
|
* with contigious address space from start to end
|
||||||
*/
|
*/
|
||||||
if (vboxSocketParseAddrUtf16(data, ipAddressUtf16,
|
if (vboxSocketParseAddrUtf16(data, ipAddressUtf16,
|
||||||
&def->ipAddress) < 0 ||
|
&ipdef->address) < 0 ||
|
||||||
vboxSocketParseAddrUtf16(data, networkMaskUtf16,
|
vboxSocketParseAddrUtf16(data, networkMaskUtf16,
|
||||||
&def->netmask) < 0 ||
|
&ipdef->netmask) < 0 ||
|
||||||
vboxSocketParseAddrUtf16(data, fromIPAddressUtf16,
|
vboxSocketParseAddrUtf16(data, fromIPAddressUtf16,
|
||||||
&def->ranges[0].start) < 0 ||
|
&ipdef->ranges[0].start) < 0 ||
|
||||||
vboxSocketParseAddrUtf16(data, toIPAddressUtf16,
|
vboxSocketParseAddrUtf16(data, toIPAddressUtf16,
|
||||||
&def->ranges[0].end) < 0) {
|
&ipdef->ranges[0].end) < 0) {
|
||||||
errorOccurred = true;
|
errorOccurred = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7462,16 +7483,16 @@ static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSE
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
def->nranges = 0;
|
ipdef->nranges = 0;
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
}
|
}
|
||||||
|
|
||||||
def->nhosts = 1;
|
ipdef->nhosts = 1;
|
||||||
if (VIR_ALLOC_N(def->hosts, def->nhosts) >=0 ) {
|
if (VIR_ALLOC_N(ipdef->hosts, ipdef->nhosts) >=0 ) {
|
||||||
def->hosts[0].name = strdup(network->name);
|
ipdef->hosts[0].name = strdup(network->name);
|
||||||
if (def->hosts[0].name == NULL) {
|
if (ipdef->hosts[0].name == NULL) {
|
||||||
VIR_FREE(def->hosts);
|
VIR_FREE(ipdef->hosts);
|
||||||
def->nhosts = 0;
|
ipdef->nhosts = 0;
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
} else {
|
} else {
|
||||||
PRUnichar *macAddressUtf16 = NULL;
|
PRUnichar *macAddressUtf16 = NULL;
|
||||||
@ -7481,10 +7502,10 @@ static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSE
|
|||||||
networkInterface->vtbl->GetHardwareAddress(networkInterface, &macAddressUtf16);
|
networkInterface->vtbl->GetHardwareAddress(networkInterface, &macAddressUtf16);
|
||||||
networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16);
|
networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16);
|
||||||
|
|
||||||
VBOX_UTF16_TO_UTF8(macAddressUtf16, &def->hosts[0].mac);
|
VBOX_UTF16_TO_UTF8(macAddressUtf16, &ipdef->hosts[0].mac);
|
||||||
|
|
||||||
if (vboxSocketParseAddrUtf16(data, ipAddressUtf16,
|
if (vboxSocketParseAddrUtf16(data, ipAddressUtf16,
|
||||||
&def->hosts[0].ip) < 0) {
|
&ipdef->hosts[0].ip) < 0) {
|
||||||
errorOccurred = true;
|
errorOccurred = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7496,7 +7517,7 @@ static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
def->nhosts = 0;
|
ipdef->nhosts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VBOX_RELEASE(dhcpServer);
|
VBOX_RELEASE(dhcpServer);
|
||||||
@ -7509,9 +7530,9 @@ static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSE
|
|||||||
networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16);
|
networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16);
|
||||||
|
|
||||||
if (vboxSocketParseAddrUtf16(data, networkMaskUtf16,
|
if (vboxSocketParseAddrUtf16(data, networkMaskUtf16,
|
||||||
&def->netmask) < 0 ||
|
&ipdef->netmask) < 0 ||
|
||||||
vboxSocketParseAddrUtf16(data, ipAddressUtf16,
|
vboxSocketParseAddrUtf16(data, ipAddressUtf16,
|
||||||
&def->ipAddress) < 0) {
|
&ipdef->address) < 0) {
|
||||||
errorOccurred = true;
|
errorOccurred = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,4 +10,12 @@
|
|||||||
<host mac="00:16:3e:3e:a9:1a" name="b.example.com" ip="192.168.122.11" />
|
<host mac="00:16:3e:3e:a9:1a" name="b.example.com" ip="192.168.122.11" />
|
||||||
</dhcp>
|
</dhcp>
|
||||||
</ip>
|
</ip>
|
||||||
|
<ip family="ipv4" address="192.168.123.1" netmask="255.255.255.0">
|
||||||
|
</ip>
|
||||||
|
<ip family="ipv6" address="2001:db8:ac10:fe01::1" prefix="64">
|
||||||
|
</ip>
|
||||||
|
<ip family="ipv6" address="2001:db8:ac10:fd01::1" prefix="64">
|
||||||
|
</ip>
|
||||||
|
<ip family="ipv4" address="10.24.10.1">
|
||||||
|
</ip>
|
||||||
</network>
|
</network>
|
||||||
|
@ -10,4 +10,12 @@
|
|||||||
<host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
|
<host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
|
||||||
</dhcp>
|
</dhcp>
|
||||||
</ip>
|
</ip>
|
||||||
|
<ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
|
||||||
|
</ip>
|
||||||
|
<ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64'>
|
||||||
|
</ip>
|
||||||
|
<ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'>
|
||||||
|
</ip>
|
||||||
|
<ip family='ipv4' address='10.24.10.1'>
|
||||||
|
</ip>
|
||||||
</network>
|
</network>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user