2008-07-11 10:48:34 +00:00
|
|
|
/*
|
|
|
|
* network_conf.c: network XML handling
|
|
|
|
*
|
2010-03-01 23:38:28 +00:00
|
|
|
* Copyright (C) 2006-2010 Red Hat, Inc.
|
2008-07-11 10:48:34 +00:00
|
|
|
* Copyright (C) 2006-2008 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2009-12-22 02:06:57 +00:00
|
|
|
#include <unistd.h>
|
2008-07-11 10:48:34 +00:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <sys/types.h>
|
2008-08-12 08:25:48 +00:00
|
|
|
#include <sys/stat.h>
|
2008-07-11 10:48:34 +00:00
|
|
|
#include <fcntl.h>
|
2008-10-28 17:45:41 +00:00
|
|
|
#include <string.h>
|
2008-07-11 10:48:34 +00:00
|
|
|
#include <dirent.h>
|
|
|
|
|
2008-11-04 22:30:33 +00:00
|
|
|
#include "virterror_internal.h"
|
2008-11-04 23:22:06 +00:00
|
|
|
#include "datatypes.h"
|
2008-07-11 10:48:34 +00:00
|
|
|
#include "network_conf.h"
|
2009-11-06 16:50:54 +00:00
|
|
|
#include "network.h"
|
2008-07-11 10:48:34 +00:00
|
|
|
#include "memory.h"
|
|
|
|
#include "xml.h"
|
|
|
|
#include "uuid.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "buf.h"
|
2008-08-20 12:50:29 +00:00
|
|
|
#include "c-ctype.h"
|
2010-10-19 14:23:51 +00:00
|
|
|
#include "files.h"
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2009-03-02 17:37:03 +00:00
|
|
|
#define MAX_BRIDGE_ID 256
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NETWORK
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
VIR_ENUM_DECL(virNetworkForward)
|
|
|
|
|
|
|
|
VIR_ENUM_IMPL(virNetworkForward,
|
|
|
|
VIR_NETWORK_FORWARD_LAST,
|
|
|
|
"none", "nat", "route" )
|
|
|
|
|
2010-03-01 23:38:28 +00:00
|
|
|
#define virNetworkReportError(code, ...) \
|
2010-02-10 10:22:52 +00:00
|
|
|
virReportErrorHelper(NULL, VIR_FROM_NETWORK, code, __FILE__, \
|
2010-03-01 23:38:28 +00:00
|
|
|
__FUNCTION__, __LINE__, __VA_ARGS__)
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const unsigned char *uuid)
|
|
|
|
{
|
2008-10-10 14:50:26 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
2008-12-04 22:00:14 +00:00
|
|
|
for (i = 0 ; i < nets->count ; i++) {
|
|
|
|
virNetworkObjLock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
if (!memcmp(nets->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
|
|
|
|
return nets->objs[i];
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
virNetworkObjPtr virNetworkFindByName(const virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const char *name)
|
|
|
|
{
|
2008-10-10 14:50:26 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
2008-12-04 22:00:14 +00:00
|
|
|
for (i = 0 ; i < nets->count ; i++) {
|
|
|
|
virNetworkObjLock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
if (STREQ(nets->objs[i]->def->name, name))
|
|
|
|
return nets->objs[i];
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void virNetworkDefFree(virNetworkDefPtr def)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->name);
|
|
|
|
VIR_FREE(def->bridge);
|
|
|
|
VIR_FREE(def->forwardDev);
|
2008-09-08 12:45:29 +00:00
|
|
|
VIR_FREE(def->domain);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
VIR_FREE(def->ranges);
|
|
|
|
|
2008-08-20 12:50:29 +00:00
|
|
|
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);
|
|
|
|
|
2009-09-21 20:50:25 +00:00
|
|
|
VIR_FREE(def->tftproot);
|
|
|
|
VIR_FREE(def->bootfile);
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
VIR_FREE(def);
|
|
|
|
}
|
|
|
|
|
|
|
|
void virNetworkObjFree(virNetworkObjPtr net)
|
|
|
|
{
|
|
|
|
if (!net)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virNetworkDefFree(net->def);
|
|
|
|
virNetworkDefFree(net->newDef);
|
|
|
|
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexDestroy(&net->lock);
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
VIR_FREE(net);
|
|
|
|
}
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
void virNetworkObjListFree(virNetworkObjListPtr nets)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0 ; i < nets->count ; i++)
|
|
|
|
virNetworkObjFree(nets->objs[i]);
|
|
|
|
|
|
|
|
VIR_FREE(nets->objs);
|
|
|
|
nets->count = 0;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkObjPtr virNetworkAssignDef(virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const virNetworkDefPtr def)
|
|
|
|
{
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
if ((network = virNetworkFindByName(nets, def->name))) {
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virNetworkObjIsActive(network)) {
|
2008-07-11 10:48:34 +00:00
|
|
|
virNetworkDefFree(network->def);
|
|
|
|
network->def = def;
|
|
|
|
} else {
|
2010-05-17 20:38:59 +00:00
|
|
|
virNetworkDefFree(network->newDef);
|
2008-07-11 10:48:34 +00:00
|
|
|
network->newDef = def;
|
|
|
|
}
|
|
|
|
|
|
|
|
return network;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(network) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-07-11 10:48:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-01-15 19:56:05 +00:00
|
|
|
if (virMutexInit(&network->lock) < 0) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2009-01-15 19:56:05 +00:00
|
|
|
"%s", _("cannot initialize mutex"));
|
|
|
|
VIR_FREE(network);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjLock(network);
|
2008-07-11 10:48:34 +00:00
|
|
|
network->def = def;
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
if (VIR_REALLOC_N(nets->objs, nets->count + 1) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-10-10 14:50:26 +00:00
|
|
|
VIR_FREE(network);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
nets->objs[nets->count] = network;
|
|
|
|
nets->count++;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
return network;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
void virNetworkRemoveInactive(virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const virNetworkObjPtr net)
|
|
|
|
{
|
2008-10-10 14:50:26 +00:00
|
|
|
unsigned int i;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(net);
|
2008-10-10 14:50:26 +00:00
|
|
|
for (i = 0 ; i < nets->count ; i++) {
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjLock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
if (nets->objs[i] == net) {
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
virNetworkObjFree(nets->objs[i]);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
if (i < (nets->count - 1))
|
|
|
|
memmove(nets->objs + i, nets->objs + i + 1,
|
|
|
|
sizeof(*(nets->objs)) * (nets->count - (i + 1)));
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
if (VIR_REALLOC_N(nets->objs, nets->count - 1) < 0) {
|
|
|
|
; /* Failure to reduce memory allocation isn't fatal */
|
|
|
|
}
|
|
|
|
nets->count--;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkDHCPRangeDefParseXML(virNetworkDefPtr def,
|
2008-07-11 10:48:34 +00:00
|
|
|
xmlNodePtr node) {
|
|
|
|
|
|
|
|
xmlNodePtr cur;
|
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
2008-08-20 12:50:29 +00:00
|
|
|
if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "range")) {
|
2009-11-06 16:50:54 +00:00
|
|
|
char *start, *end;
|
|
|
|
virSocketAddr saddr, eaddr;
|
|
|
|
int range;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2010-11-24 20:08:55 +00:00
|
|
|
if (!(start = virXMLPropString(cur, "start"))) {
|
2008-08-20 12:50:29 +00:00
|
|
|
cur = cur->next;
|
|
|
|
continue;
|
|
|
|
}
|
2010-11-24 20:08:55 +00:00
|
|
|
if (!(end = virXMLPropString(cur, "end"))) {
|
|
|
|
VIR_FREE(start);
|
2008-08-20 12:50:29 +00:00
|
|
|
cur = cur->next;
|
2009-11-06 16:50:54 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-10-20 13:26:30 +00:00
|
|
|
if (virSocketParseAddr(start, &saddr, AF_UNSPEC) < 0) {
|
2010-11-24 20:08:55 +00:00
|
|
|
VIR_FREE(start);
|
|
|
|
VIR_FREE(end);
|
2010-10-20 14:20:37 +00:00
|
|
|
return -1;
|
2009-11-06 16:50:54 +00:00
|
|
|
}
|
2010-10-20 13:26:30 +00:00
|
|
|
if (virSocketParseAddr(end, &eaddr, AF_UNSPEC) < 0) {
|
2010-11-24 20:08:55 +00:00
|
|
|
VIR_FREE(start);
|
|
|
|
VIR_FREE(end);
|
2010-10-20 14:20:37 +00:00
|
|
|
return -1;
|
2009-11-06 16:50:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
range = virSocketGetRange(&saddr, &eaddr);
|
|
|
|
if (range < 0) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_XML_ERROR,
|
2009-11-06 16:50:54 +00:00
|
|
|
_("dhcp range '%s' to '%s' invalid"),
|
|
|
|
start, end);
|
2010-11-24 20:08:55 +00:00
|
|
|
VIR_FREE(start);
|
|
|
|
VIR_FREE(end);
|
2010-10-20 14:20:37 +00:00
|
|
|
return -1;
|
2008-08-20 12:50:29 +00:00
|
|
|
}
|
2010-11-24 20:29:38 +00:00
|
|
|
VIR_FREE(start);
|
|
|
|
VIR_FREE(end);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-08-20 12:50:29 +00:00
|
|
|
if (VIR_REALLOC_N(def->ranges, def->nranges + 1) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-08-20 12:50:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
def->ranges[def->nranges].start = saddr;
|
|
|
|
def->ranges[def->nranges].end = eaddr;
|
2008-08-20 12:50:29 +00:00
|
|
|
def->nranges++;
|
|
|
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "host")) {
|
2010-11-24 20:08:55 +00:00
|
|
|
char *mac, *name, *ip;
|
2008-08-20 12:50:29 +00:00
|
|
|
unsigned char addr[6];
|
2010-10-21 10:13:05 +00:00
|
|
|
virSocketAddr inaddr;
|
2008-08-20 12:50:29 +00:00
|
|
|
|
2010-11-24 20:08:55 +00:00
|
|
|
mac = virXMLPropString(cur, "mac");
|
2008-08-20 12:50:29 +00:00
|
|
|
if ((mac != NULL) &&
|
2010-11-24 20:08:55 +00:00
|
|
|
(virParseMacAddr(mac, &addr[0]) != 0)) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-08-20 12:50:29 +00:00
|
|
|
_("cannot parse MAC address '%s'"),
|
|
|
|
mac);
|
|
|
|
VIR_FREE(mac);
|
|
|
|
}
|
2010-11-24 20:08:55 +00:00
|
|
|
name = virXMLPropString(cur, "name");
|
2008-08-20 12:50:29 +00:00
|
|
|
if ((name != NULL) && (!c_isalpha(name[0]))) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-08-20 12:50:29 +00:00
|
|
|
_("cannot use name address '%s'"),
|
|
|
|
name);
|
|
|
|
VIR_FREE(name);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* You need at least one MAC address or one host name
|
|
|
|
*/
|
|
|
|
if ((mac == NULL) && (name == NULL)) {
|
|
|
|
VIR_FREE(mac);
|
|
|
|
VIR_FREE(name);
|
|
|
|
cur = cur->next;
|
|
|
|
continue;
|
|
|
|
}
|
2010-11-24 20:08:55 +00:00
|
|
|
ip = virXMLPropString(cur, "ip");
|
|
|
|
if (virSocketParseAddr(ip, &inaddr, AF_UNSPEC) < 0) {
|
2008-08-20 12:50:29 +00:00
|
|
|
VIR_FREE(ip);
|
|
|
|
VIR_FREE(mac);
|
|
|
|
VIR_FREE(name);
|
|
|
|
cur = cur->next;
|
|
|
|
continue;
|
|
|
|
}
|
2010-11-24 20:29:38 +00:00
|
|
|
VIR_FREE(ip);
|
2008-08-20 12:50:29 +00:00
|
|
|
if (VIR_REALLOC_N(def->hosts, def->nhosts + 1) < 0) {
|
|
|
|
VIR_FREE(mac);
|
|
|
|
VIR_FREE(name);
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-08-20 12:50:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2010-11-24 20:08:55 +00:00
|
|
|
def->hosts[def->nhosts].mac = mac;
|
|
|
|
def->hosts[def->nhosts].name = name;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
def->hosts[def->nhosts].ip = inaddr;
|
2008-08-20 12:50:29 +00:00
|
|
|
def->nhosts++;
|
2009-09-21 20:50:25 +00:00
|
|
|
|
|
|
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "bootp")) {
|
2010-11-24 20:08:55 +00:00
|
|
|
char *file;
|
|
|
|
char *server;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
virSocketAddr inaddr;
|
2010-10-22 12:28:04 +00:00
|
|
|
memset(&inaddr, 0, sizeof(inaddr));
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-24 20:08:55 +00:00
|
|
|
if (!(file = virXMLPropString(cur, "file"))) {
|
2009-09-21 20:50:25 +00:00
|
|
|
cur = cur->next;
|
|
|
|
continue;
|
|
|
|
}
|
2010-11-24 20:08:55 +00:00
|
|
|
server = virXMLPropString(cur, "server");
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
|
2010-10-22 12:28:04 +00:00
|
|
|
if (server &&
|
2010-11-24 20:29:38 +00:00
|
|
|
virSocketParseAddr(server, &inaddr, AF_UNSPEC) < 0) {
|
|
|
|
VIR_FREE(file);
|
|
|
|
VIR_FREE(server);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
return -1;
|
2010-11-24 20:29:38 +00:00
|
|
|
}
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-24 20:08:55 +00:00
|
|
|
def->bootfile = file;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
def->bootserver = inaddr;
|
2010-11-24 20:29:38 +00:00
|
|
|
VIR_FREE(server);
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-21 20:50:25 +00:00
|
|
|
static int
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkIPParseXML(virNetworkDefPtr def,
|
2009-09-21 20:50:25 +00:00
|
|
|
xmlNodePtr node) {
|
|
|
|
xmlNodePtr cur;
|
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "dhcp")) {
|
2010-02-10 10:22:52 +00:00
|
|
|
int result = virNetworkDHCPRangeDefParseXML(def, cur);
|
2009-09-21 20:50:25 +00:00
|
|
|
if (result)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "tftp")) {
|
2010-11-24 20:08:55 +00:00
|
|
|
char *root;
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-24 20:08:55 +00:00
|
|
|
if (!(root = virXMLPropString(cur, "root"))) {
|
2009-09-21 20:50:25 +00:00
|
|
|
cur = cur->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-11-24 20:08:55 +00:00
|
|
|
def->tftproot = root;
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
static virNetworkDefPtr
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkDefParseXML(xmlXPathContextPtr ctxt)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
|
|
|
virNetworkDefPtr def;
|
|
|
|
char *tmp;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
char *ipAddress;
|
|
|
|
char *netmask;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(def) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-07-11 10:48:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Extract network name */
|
2010-02-04 21:52:34 +00:00
|
|
|
def->name = virXPathString("string(./name[1])", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
if (!def->name) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_NO_NAME, NULL);
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Extract network uuid */
|
2010-02-04 21:52:34 +00:00
|
|
|
tmp = virXPathString("string(./uuid[1])", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
if (!tmp) {
|
2009-09-04 17:15:51 +00:00
|
|
|
if (virUUIDGenerate(def->uuid)) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2009-01-20 17:13:33 +00:00
|
|
|
"%s", _("Failed to generate UUID"));
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (virUUIDParse(tmp, def->uuid) < 0) {
|
|
|
|
VIR_FREE(tmp);
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-07-11 10:48:34 +00:00
|
|
|
"%s", _("malformed uuid element"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
}
|
|
|
|
|
2008-09-08 12:45:29 +00:00
|
|
|
/* Parse network domain information */
|
2010-02-04 21:52:34 +00:00
|
|
|
def->domain = virXPathString("string(./domain[1]/@name)", ctxt);
|
2008-09-08 12:45:29 +00:00
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
/* Parse bridge information */
|
2010-02-04 21:52:34 +00:00
|
|
|
def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt);
|
|
|
|
tmp = virXPathString("string(./bridge[1]/@stp)", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
def->stp = (tmp && STREQ(tmp, "off")) ? 0 : 1;
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
|
2010-02-04 21:52:34 +00:00
|
|
|
if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0)
|
2008-07-11 10:48:34 +00:00
|
|
|
def->delay = 0;
|
|
|
|
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
ipAddress = virXPathString("string(./ip[1]/@address)", ctxt);
|
|
|
|
netmask = virXPathString("string(./ip[1]/@netmask)", ctxt);
|
|
|
|
if (ipAddress &&
|
|
|
|
netmask) {
|
2009-09-21 20:50:25 +00:00
|
|
|
xmlNodePtr ip;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (virSocketParseAddr(ipAddress, &def->ipAddress, AF_UNSPEC) < 0)
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (virSocketParseAddr(netmask, &def->netmask, AF_UNSPEC) < 0)
|
2010-10-21 10:13:05 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* XXX someday we want IPv6, so will need to relax this */
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (!VIR_SOCKET_IS_FAMILY(&def->ipAddress, AF_INET) ||
|
|
|
|
!VIR_SOCKET_IS_FAMILY(&def->netmask, AF_INET)) {
|
2010-10-21 10:13:05 +00:00
|
|
|
virNetworkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s", _("Only IPv4 addresses are supported"));
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2010-02-04 21:52:34 +00:00
|
|
|
if ((ip = virXPathNode("./ip[1]", ctxt)) &&
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkIPParseXML(def, ip) < 0)
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
VIR_FREE(ipAddress);
|
|
|
|
VIR_FREE(netmask);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* IPv4 forwarding setup */
|
2010-02-04 21:52:34 +00:00
|
|
|
if (virXPathBoolean("count(./forward) > 0", ctxt)) {
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (def->ipAddress.data.sa.sa_family != AF_INET ||
|
|
|
|
def->netmask.data.sa.sa_family != AF_INET) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-07-11 10:48:34 +00:00
|
|
|
"%s", _("Forwarding requested, but no IPv4 address/netmask provided"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2010-02-04 21:52:34 +00:00
|
|
|
tmp = virXPathString("string(./forward[1]/@mode)", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
if (tmp) {
|
|
|
|
if ((def->forwardType = virNetworkForwardTypeFromString(tmp)) < 0) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-07-11 10:48:34 +00:00
|
|
|
_("unknown forwarding type '%s'"), tmp);
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
} else {
|
|
|
|
def->forwardType = VIR_NETWORK_FORWARD_NAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-04 21:52:34 +00:00
|
|
|
def->forwardDev = virXPathString("string(./forward[1]/@dev)", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
} else {
|
|
|
|
def->forwardType = VIR_NETWORK_FORWARD_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return def;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virNetworkDefFree(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-24 20:53:16 +00:00
|
|
|
static virNetworkDefPtr
|
|
|
|
virNetworkDefParse(const char *xmlStr,
|
|
|
|
const char *filename)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
2010-02-24 20:53:16 +00:00
|
|
|
xmlDocPtr xml;
|
2008-08-01 09:39:44 +00:00
|
|
|
virNetworkDefPtr def = NULL;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2010-02-24 20:53:16 +00:00
|
|
|
if ((xml = virXMLParse(filename, xmlStr, "network.xml"))) {
|
|
|
|
def = virNetworkDefParseNode(xml, xmlDocGetRootElement(xml));
|
|
|
|
xmlFreeDoc(xml);
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2010-02-24 20:53:16 +00:00
|
|
|
virNetworkDefPtr virNetworkDefParseString(const char *xmlStr)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
2010-02-24 20:53:16 +00:00
|
|
|
return virNetworkDefParse(xmlStr, NULL);
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2010-02-24 20:53:16 +00:00
|
|
|
virNetworkDefPtr virNetworkDefParseFile(const char *filename)
|
|
|
|
{
|
|
|
|
return virNetworkDefParse(NULL, filename);
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml,
|
2008-07-11 10:48:34 +00:00
|
|
|
xmlNodePtr root)
|
|
|
|
{
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
virNetworkDefPtr def = NULL;
|
|
|
|
|
|
|
|
if (!xmlStrEqual(root->name, BAD_CAST "network")) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-07-11 10:48:34 +00:00
|
|
|
"%s", _("incorrect root element"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (ctxt == NULL) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctxt->node = root;
|
2010-02-10 10:22:52 +00:00
|
|
|
def = virNetworkDefParseXML(ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
char *virNetworkDefFormat(const virNetworkDefPtr def)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
unsigned char *uuid;
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
virBufferAddLit(&buf, "<network>\n");
|
|
|
|
virBufferEscapeString(&buf, " <name>%s</name>\n", def->name);
|
|
|
|
|
|
|
|
uuid = def->uuid;
|
|
|
|
virUUIDFormat(uuid, uuidstr);
|
|
|
|
virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
|
|
|
|
|
|
|
|
if (def->forwardType != VIR_NETWORK_FORWARD_NONE) {
|
|
|
|
const char *mode = virNetworkForwardTypeToString(def->forwardType);
|
|
|
|
if (mode) {
|
|
|
|
if (def->forwardDev) {
|
|
|
|
virBufferEscapeString(&buf, " <forward dev='%s'",
|
|
|
|
def->forwardDev);
|
|
|
|
} else {
|
|
|
|
virBufferAddLit(&buf, " <forward");
|
|
|
|
}
|
|
|
|
virBufferVSprintf(&buf, " mode='%s'/>\n", mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(&buf, " <bridge");
|
|
|
|
if (def->bridge)
|
|
|
|
virBufferEscapeString(&buf, " name='%s'", def->bridge);
|
2009-10-13 15:31:27 +00:00
|
|
|
virBufferVSprintf(&buf, " stp='%s' delay='%ld' />\n",
|
2008-07-11 10:48:34 +00:00
|
|
|
def->stp ? "on" : "off",
|
|
|
|
def->delay);
|
|
|
|
|
2009-07-02 14:02:18 +00:00
|
|
|
if (def->domain)
|
|
|
|
virBufferVSprintf(&buf, " <domain name='%s'/>\n", def->domain);
|
|
|
|
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (VIR_SOCKET_HAS_ADDR(&def->ipAddress) ||
|
|
|
|
VIR_SOCKET_HAS_ADDR(&def->netmask)) {
|
2008-07-11 10:48:34 +00:00
|
|
|
virBufferAddLit(&buf, " <ip");
|
|
|
|
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (VIR_SOCKET_HAS_ADDR(&def->ipAddress)) {
|
|
|
|
char *addr = virSocketFormatAddr(&def->ipAddress);
|
|
|
|
if (!addr)
|
|
|
|
goto error;
|
|
|
|
virBufferVSprintf(&buf, " address='%s'", addr);
|
|
|
|
VIR_FREE(addr);
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (VIR_SOCKET_HAS_ADDR(&def->netmask)) {
|
|
|
|
char *addr = virSocketFormatAddr(&def->netmask);
|
|
|
|
if (!addr)
|
|
|
|
goto error;
|
|
|
|
virBufferVSprintf(&buf, " netmask='%s'", addr);
|
|
|
|
VIR_FREE(addr);
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
virBufferAddLit(&buf, ">\n");
|
|
|
|
|
2009-09-21 20:50:25 +00:00
|
|
|
if (def->tftproot) {
|
|
|
|
virBufferEscapeString(&buf, " <tftp root='%s' />\n",
|
|
|
|
def->tftproot);
|
|
|
|
}
|
2008-08-20 12:50:29 +00:00
|
|
|
if ((def->nranges || def->nhosts)) {
|
2008-07-11 10:48:34 +00:00
|
|
|
int i;
|
|
|
|
virBufferAddLit(&buf, " <dhcp>\n");
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
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;
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
virBufferVSprintf(&buf, " <range start='%s' end='%s' />\n",
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
saddr, eaddr);
|
|
|
|
VIR_FREE(saddr);
|
|
|
|
VIR_FREE(eaddr);
|
|
|
|
}
|
2008-08-20 12:50:29 +00:00
|
|
|
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);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
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);
|
|
|
|
}
|
2008-08-20 12:50:29 +00:00
|
|
|
virBufferAddLit(&buf, "/>\n");
|
|
|
|
}
|
2009-09-21 20:50:25 +00:00
|
|
|
if (def->bootfile) {
|
2009-10-28 14:57:49 +00:00
|
|
|
virBufferEscapeString(&buf, " <bootp file='%s' ",
|
2009-09-21 20:50:25 +00:00
|
|
|
def->bootfile);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (VIR_SOCKET_HAS_ADDR(&def->bootserver)) {
|
|
|
|
char *ipaddr = virSocketFormatAddr(&def->bootserver);
|
|
|
|
if (!ipaddr)
|
|
|
|
goto error;
|
|
|
|
virBufferEscapeString(&buf, "server='%s' ", ipaddr);
|
|
|
|
VIR_FREE(ipaddr);
|
2009-10-28 14:57:49 +00:00
|
|
|
}
|
|
|
|
virBufferAddLit(&buf, "/>\n");
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
virBufferAddLit(&buf, " </dhcp>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(&buf, " </ip>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(&buf, "</network>\n");
|
|
|
|
|
|
|
|
if (virBufferError(&buf))
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
|
|
|
|
no_memory:
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
error:
|
2009-12-09 23:00:50 +00:00
|
|
|
virBufferFreeAndReset(&buf);
|
2008-07-11 10:48:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkSaveXML(const char *configDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
virNetworkDefPtr def,
|
|
|
|
const char *xml)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
2009-01-20 22:36:10 +00:00
|
|
|
char *configFile = NULL;
|
2008-07-11 10:48:34 +00:00
|
|
|
int fd = -1, ret = -1;
|
|
|
|
size_t towrite;
|
|
|
|
int err;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((configFile = virNetworkConfigFile(configDir, def->name)) == NULL)
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((err = virFileMakePath(configDir))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create config directory '%s'"),
|
|
|
|
configDir);
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if ((fd = open(configFile,
|
2008-07-11 10:48:34 +00:00
|
|
|
O_WRONLY | O_CREAT | O_TRUNC,
|
|
|
|
S_IRUSR | S_IWUSR )) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create config file '%s'"),
|
2009-01-20 22:36:10 +00:00
|
|
|
configFile);
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
towrite = strlen(xml);
|
|
|
|
if (safewrite(fd, xml, towrite) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot write config file '%s'"),
|
2009-01-20 22:36:10 +00:00
|
|
|
configFile);
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-10-19 14:23:51 +00:00
|
|
|
if (VIR_CLOSE(fd) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot save config file '%s'"),
|
2009-01-20 22:36:10 +00:00
|
|
|
configFile);
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2010-10-19 14:23:51 +00:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
VIR_FREE(configFile);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkSaveConfig(const char *configDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
virNetworkDefPtr def)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
char *xml;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(xml = virNetworkDefFormat(def)))
|
2009-01-20 22:36:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkSaveXML(configDir, def, xml))
|
2009-01-20 22:36:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(xml);
|
2008-07-11 10:48:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const char *configDir,
|
|
|
|
const char *autostartDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
const char *name)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
|
|
|
char *configFile = NULL, *autostartLink = NULL;
|
|
|
|
virNetworkDefPtr def = NULL;
|
|
|
|
virNetworkObjPtr net;
|
|
|
|
int autostart;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((configFile = virNetworkConfigFile(configDir, name)) == NULL)
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((autostartLink = virNetworkConfigFile(autostartDir, name)) == NULL)
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(def = virNetworkDefParseFile(configFile)))
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (!STREQ(name, def->name)) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-07-11 10:48:34 +00:00
|
|
|
_("Network config filename '%s'"
|
|
|
|
" does not match network name '%s'"),
|
|
|
|
configFile, def->name);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2009-05-29 14:18:57 +00:00
|
|
|
/* Generate a bridge if none is specified, but don't check for collisions
|
2009-03-02 17:37:03 +00:00
|
|
|
* if a bridge is hardcoded, so the network is at least defined
|
|
|
|
*/
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkSetBridgeName(nets, def, 0))
|
2009-03-02 17:37:03 +00:00
|
|
|
goto error;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(net = virNetworkAssignDef(nets, def)))
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
net->autostart = autostart;
|
2009-03-02 17:29:44 +00:00
|
|
|
net->persistent = 1;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
return net;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
|
|
|
virNetworkDefFree(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkLoadAllConfigs(virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const char *configDir,
|
|
|
|
const char *autostartDir)
|
|
|
|
{
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *entry;
|
|
|
|
|
|
|
|
if (!(dir = opendir(configDir))) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
return 0;
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to open dir '%s'"),
|
|
|
|
configDir);
|
2008-07-11 10:48:34 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((entry = readdir(dir))) {
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjPtr net;
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
if (entry->d_name[0] == '.')
|
|
|
|
continue;
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (!virFileStripSuffix(entry->d_name, ".xml"))
|
2008-07-11 10:48:34 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* NB: ignoring errors, so one malformed config doesn't
|
|
|
|
kill the whole process */
|
2010-02-10 10:22:52 +00:00
|
|
|
net = virNetworkLoadConfig(nets,
|
2008-12-04 22:00:14 +00:00
|
|
|
configDir,
|
|
|
|
autostartDir,
|
|
|
|
entry->d_name);
|
|
|
|
if (net)
|
|
|
|
virNetworkObjUnlock(net);
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkDeleteConfig(const char *configDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
const char *autostartDir,
|
2008-07-11 10:48:34 +00:00
|
|
|
virNetworkObjPtr net)
|
|
|
|
{
|
2009-01-20 22:36:10 +00:00
|
|
|
char *configFile = NULL;
|
|
|
|
char *autostartLink = NULL;
|
2009-09-04 13:56:32 +00:00
|
|
|
int ret = -1;
|
2009-01-20 22:36:10 +00:00
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((configFile = virNetworkConfigFile(configDir, net->def->name)) == NULL)
|
2009-01-20 22:36:10 +00:00
|
|
|
goto error;
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((autostartLink = virNetworkConfigFile(autostartDir, net->def->name)) == NULL)
|
2009-01-20 22:36:10 +00:00
|
|
|
goto error;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
/* Not fatal if this doesn't work */
|
2009-01-20 22:36:10 +00:00
|
|
|
unlink(autostartLink);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (unlink(configFile) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot remove config file '%s'"),
|
2009-01-20 22:36:10 +00:00
|
|
|
configFile);
|
|
|
|
goto error;
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 13:56:32 +00:00
|
|
|
ret = 0;
|
2009-01-20 22:36:10 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
2009-09-04 13:56:32 +00:00
|
|
|
return ret;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
char *virNetworkConfigFile(const char *dir,
|
2009-01-20 22:36:10 +00:00
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
char *ret = NULL;
|
|
|
|
|
|
|
|
if (virAsprintf(&ret, "%s/%s.xml", dir, name) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-01-20 22:36:10 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
2008-12-04 20:53:20 +00:00
|
|
|
|
2009-03-02 17:37:03 +00:00
|
|
|
int virNetworkBridgeInUse(const virNetworkObjListPtr nets,
|
|
|
|
const char *bridge,
|
|
|
|
const char *skipname)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
unsigned int ret = 0;
|
|
|
|
|
|
|
|
for (i = 0 ; i < nets->count ; i++) {
|
|
|
|
virNetworkObjLock(nets->objs[i]);
|
|
|
|
if (nets->objs[i]->def->bridge &&
|
|
|
|
STREQ(nets->objs[i]->def->bridge, bridge) &&
|
|
|
|
!(skipname && STREQ(nets->objs[i]->def->name, skipname)))
|
|
|
|
ret = 1;
|
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
char *virNetworkAllocateBridge(const virNetworkObjListPtr nets,
|
2009-04-21 19:00:06 +00:00
|
|
|
const char *template)
|
2009-03-02 17:37:03 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
int id = 0;
|
|
|
|
char *newname;
|
|
|
|
|
2009-04-21 19:00:06 +00:00
|
|
|
if (!template)
|
|
|
|
template = "virbr%d";
|
|
|
|
|
2009-03-02 17:37:03 +00:00
|
|
|
do {
|
2010-08-31 20:25:49 +00:00
|
|
|
if (virAsprintf(&newname, template, id) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (!virNetworkBridgeInUse(nets, newname, NULL)) {
|
2009-03-02 17:37:03 +00:00
|
|
|
return newname;
|
|
|
|
}
|
2010-08-31 20:25:49 +00:00
|
|
|
VIR_FREE(newname);
|
2009-03-02 17:37:03 +00:00
|
|
|
|
|
|
|
id++;
|
2009-03-02 17:56:50 +00:00
|
|
|
} while (id <= MAX_BRIDGE_ID);
|
2009-03-02 17:37:03 +00:00
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
2009-03-02 17:37:03 +00:00
|
|
|
_("Bridge generation exceeded max id %d"),
|
|
|
|
MAX_BRIDGE_ID);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkSetBridgeName(const virNetworkObjListPtr nets,
|
2009-05-29 14:18:57 +00:00
|
|
|
virNetworkDefPtr def,
|
|
|
|
int check_collision) {
|
2009-03-02 17:37:03 +00:00
|
|
|
|
|
|
|
int ret = -1;
|
|
|
|
|
2009-04-21 19:00:06 +00:00
|
|
|
if (def->bridge && !strstr(def->bridge, "%d")) {
|
2009-05-29 14:18:57 +00:00
|
|
|
/* We may want to skip collision detection in this case (ex. when
|
|
|
|
* loading configs at daemon startup, so the network is at least
|
|
|
|
* defined. */
|
|
|
|
if (check_collision &&
|
|
|
|
virNetworkBridgeInUse(nets, def->bridge, def->name)) {
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("bridge name '%s' already in use."),
|
|
|
|
def->bridge);
|
2009-03-02 17:37:03 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Allocate a bridge name */
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(def->bridge = virNetworkAllocateBridge(nets, def->bridge)))
|
2009-03-02 17:37:03 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
error:
|
|
|
|
return ret;
|
|
|
|
}
|
2009-01-20 22:36:10 +00:00
|
|
|
|
2010-05-27 15:44:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* virNetworkObjIsDuplicate:
|
|
|
|
* @doms : virNetworkObjListPtr to search
|
|
|
|
* @def : virNetworkDefPtr definition of network to lookup
|
|
|
|
* @check_active: If true, ensure that network is not active
|
|
|
|
*
|
|
|
|
* Returns: -1 on error
|
|
|
|
* 0 if network is new
|
|
|
|
* 1 if network is a duplicate
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virNetworkObjIsDuplicate(virNetworkObjListPtr doms,
|
|
|
|
virNetworkDefPtr def,
|
|
|
|
unsigned int check_active)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
int dupVM = 0;
|
|
|
|
virNetworkObjPtr vm = NULL;
|
|
|
|
|
|
|
|
/* See if a VM with matching UUID already exists */
|
|
|
|
vm = virNetworkFindByUUID(doms, def->uuid);
|
|
|
|
if (vm) {
|
|
|
|
/* UUID matches, but if names don't match, refuse it */
|
|
|
|
if (STRNEQ(vm->def->name, def->name)) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
|
virNetworkReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("network '%s' is already defined with uuid %s"),
|
|
|
|
vm->def->name, uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (check_active) {
|
|
|
|
/* UUID & name match, but if VM is already active, refuse it */
|
|
|
|
if (virNetworkObjIsActive(vm)) {
|
|
|
|
virNetworkReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("network is already active as '%s'"),
|
|
|
|
vm->def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dupVM = 1;
|
|
|
|
} else {
|
|
|
|
/* UUID does not match, but if a name matches, refuse it */
|
|
|
|
vm = virNetworkFindByName(doms, def->name);
|
|
|
|
if (vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
|
|
|
virNetworkReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("network '%s' already exists with uuid %s"),
|
|
|
|
def->name, uuidstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = dupVM;
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virNetworkObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-04 22:00:14 +00:00
|
|
|
void virNetworkObjLock(virNetworkObjPtr obj)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexLock(&obj->lock);
|
2008-12-04 22:00:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void virNetworkObjUnlock(virNetworkObjPtr obj)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexUnlock(&obj->lock);
|
2008-12-04 20:53:20 +00:00
|
|
|
}
|