---
src/lxc/lxc_native.c | 144 +++++++++++++++---------
tests/lxcconf2xmldata/lxcconf2xml-simple.config | 2 +
tests/lxcconf2xmldata/lxcconf2xml-simple.xml | 2 +
3 files changed, 97 insertions(+), 51 deletions(-)
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 41e069f..3c8f928 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -413,79 +413,83 @@ lxcCreateHostdevDef(int mode, int type, const char *data)
return hostdev;
}
+typedef struct {
+ virDomainDefPtr def;
+ char *type;
+ char *link;
+ char *mac;
+ char *flag;
+ char *macvlanmode;
+ char *vlanid;
+ char *name;
+ virDomainNetIpDefPtr *ips;
+ size_t nips;
+ bool privnet;
+ size_t networks;
+} lxcNetworkParseData;
+
static int
-lxcAddNetworkDefinition(virDomainDefPtr def,
- const char *type,
- const char *linkdev,
- const char *mac,
- const char *flag,
- const char *macvlanmode,
- const char *vlanid,
- const char *name)
+lxcAddNetworkDefinition(lxcNetworkParseData *data)
{
virDomainNetDefPtr net = NULL;
virDomainHostdevDefPtr hostdev = NULL;
bool isPhys, isVlan = false;
+ size_t i;
- if ((type == NULL) || STREQ(type, "empty") || STREQ(type, "") ||
- STREQ(type, "none"))
+ if ((data->type == NULL) || STREQ(data->type, "empty") ||
+ STREQ(data->type, "") || STREQ(data->type, "none"))
return 0;
- isPhys = STREQ(type, "phys");
- isVlan = STREQ(type, "vlan");
- if (type != NULL && (isPhys || isVlan)) {
- if (!linkdev) {
+ isPhys = STREQ(data->type, "phys");
+ isVlan = STREQ(data->type, "vlan");
+ if (data->type != NULL && (isPhys || isVlan)) {
+ if (!data->link) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Missing 'link' attribute for NIC"));
goto error;
}
if (!(hostdev = lxcCreateHostdevDef(VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES,
VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET,
- linkdev)))
+ data->link)))
goto error;
/* This still requires the user to manually setup the vlan interface
* on the host */
- if (isVlan && vlanid) {
+ if (isVlan && data->vlanid) {
VIR_FREE(hostdev->source.caps.u.net.iface);
if (virAsprintf(&hostdev->source.caps.u.net.iface,
- "%s.%s", linkdev, vlanid) < 0)
+ "%s.%s", data->link, data->vlanid) < 0)
goto error;
}
- if (VIR_EXPAND_N(def->hostdevs, def->nhostdevs, 1) < 0)
+ if (VIR_EXPAND_N(data->def->hostdevs, data->def->nhostdevs, 1) <
0)
goto error;
- def->hostdevs[def->nhostdevs - 1] = hostdev;
+ data->def->hostdevs[data->def->nhostdevs - 1] = hostdev;
} else {
- if (!(net = lxcCreateNetDef(type, linkdev, mac, flag, macvlanmode, name)))
+ if (!(net = lxcCreateNetDef(data->type, data->link, data->mac,
+ data->flag, data->macvlanmode,
+ data->name)))
goto error;
- if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
+ net->ips = data->ips;
+ net->nips = data->nips;
+
+ if (VIR_EXPAND_N(data->def->nets, data->def->nnets, 1) < 0)
goto error;
- def->nets[def->nnets - 1] = net;
+ data->def->nets[data->def->nnets - 1] = net;
}
return 1;
error:
+ for (i = 0; i < data->nips; i++)
+ VIR_FREE(data->ips[i]);
+ VIR_FREE(data->ips);
virDomainNetDefFree(net);
virDomainHostdevDefFree(hostdev);
return -1;
}
-typedef struct {
- virDomainDefPtr def;
- char *type;
- char *link;
- char *mac;
- char *flag;
- char *macvlanmode;
- char *vlanid;
- char *name;
- bool privnet;
- size_t networks;
-} lxcNetworkParseData;
-
static int
lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
{
@@ -494,12 +498,7 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void
*data)
if (STREQ(name, "lxc.network.type")) {
/* Store the previous NIC */
- status = lxcAddNetworkDefinition(parseData->def, parseData->type,
- parseData->link, parseData->mac,
- parseData->flag,
- parseData->macvlanmode,
- parseData->vlanid,
- parseData->name);
+ status = lxcAddNetworkDefinition(parseData);
if (status < 0)
return -1;
@@ -517,6 +516,9 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void
*data)
parseData->vlanid = NULL;
parseData->name = NULL;
+ parseData->ips = NULL;
+ parseData->nips = 0;
+
/* Keep the new value */
parseData->type = value->str;
}
@@ -532,10 +534,42 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void
*data)
parseData->vlanid = value->str;
else if (STREQ(name, "lxc.network.name"))
parseData->name = value->str;
- else if (STRPREFIX(name, "lxc.network"))
+ else if (STREQ(name, "lxc.network.ipv4") ||
+ STREQ(name, "lxc.network.ipv6")) {
+ int family = AF_INET;
+ char **ipparts = NULL;
+ virDomainNetIpDefPtr ip = NULL;
+
+ if (VIR_ALLOC(ip) < 0)
+ return -1;
+
+ if (STREQ(name, "lxc.network.ipv6"))
+ family = AF_INET6;
+
+ ipparts = virStringSplit(value->str, "/", 2);
+ if (virStringListLength(ipparts) != 2 ||
+ virSocketAddrParse(&ip->address, ipparts[0], family) < 0 ||
+ virStrToLong_ui(ipparts[1], NULL, 10, &ip->prefix) < 0) {
+
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("Invalid CIDR address: '%s'"),
value->str);
+
+ virStringFreeList(ipparts);
+ VIR_FREE(ip);
+ return -1;
+ }
+
+ virStringFreeList(ipparts);
+
+ if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) {
+ VIR_FREE(ip);
+ return -1;
+ }
+ } else if (STRPREFIX(name, "lxc.network")) {
VIR_WARN("Unhandled network property: %s = %s",
name,
value->str);
+ }
return 0;
}
@@ -544,19 +578,20 @@ static int
lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties)
{
int status;
+ int result = -1;
+ size_t i;
lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, true, 0};
+ NULL, NULL, NULL, NULL, 0, true, 0};
+
+ if (virConfWalk(properties, lxcNetworkWalkCallback, &data) < 0)
+ goto error;
- virConfWalk(properties, lxcNetworkWalkCallback, &data);
/* Add the last network definition found */
- status = lxcAddNetworkDefinition(def, data.type, data.link,
- data.mac, data.flag,
- data.macvlanmode,
- data.vlanid,
- data.name);
+ status = lxcAddNetworkDefinition(&data);
+
if (status < 0)
- return -1;
+ goto error;
else if (status > 0)
data.networks++;
else if (data.type != NULL && STREQ(data.type, "none"))
@@ -566,8 +601,15 @@ lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr
properties)
/* When no network type is provided LXC only adds loopback */
def->features[VIR_DOMAIN_FEATURE_PRIVNET] = VIR_TRISTATE_SWITCH_ON;
}
+ result = 0;
- return 0;
+ return result;
+
+ error:
+ for (i = 0; i < data.nips; i++)
+ VIR_FREE(data.ips[i]);
+ VIR_FREE(data.ips);
+ return -1;
}
static int
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.config
b/tests/lxcconf2xmldata/lxcconf2xml-simple.config
index b90abc1..d417ba0 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.config
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.config
@@ -6,6 +6,8 @@ lxc.network.flags = up
lxc.network.link = virbr0
lxc.network.hwaddr = 02:00:15:8f:05:c1
lxc.network.name = eth0
+lxc.network.ipv4 = 192.168.122.2/24
+lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64
#remove next line if host DNS configuration should not be available to container
lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
index 10428ec..0dbbc71 100644
--- a/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
+++ b/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
@@ -37,6 +37,8 @@
<interface type='bridge'>
<mac address='02:00:15:8f:05:c1'/>
<source bridge='virbr0'/>
+ <ip address='192.168.122.2' family='ipv4'
prefix='24'/>
+ <ip address='2003:db8:1:0:214:1234:fe0b:3596' family='ipv6'
prefix='64'/>
<guest dev='eth0'/>
<link state='up'/>
</interface>
--
2.1.2