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)
{
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;
parseData->vlanid = NULL;
parseData->name = NULL;
+ parseData->ips = NULL;
+ parseData->nips = 0;
+
/* Keep the new value */
parseData->type = value->str;
}
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;
}
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"))
/* 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