--- /dev/null
+/*
+ * interface_conf.c: interfaces XML handling
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * 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 Veillard <veillard@redhat.com>
+ * Laine Stump <laine@redhat.com>
+ */
+
+#include <config.h>
+#include "virterror_internal.h"
+#include "datatypes.h"
+
+#include "interface_conf.h"
+
+#include "memory.h"
+#include "xml.h"
+#include "uuid.h"
+#include "util.h"
+#include "buf.h"
+
+#define VIR_FROM_THIS VIR_FROM_INTERFACE
+
+VIR_ENUM_IMPL(virInterface,
+ VIR_INTERFACE_TYPE_LAST,
+ "ethernet", "bridge", "bond", "vlan" )
+
+#define virInterfaceReportError(conn, code, fmt...) \
+ virReportErrorHelper(conn, VIR_FROM_INTERFACE, code, __FILE__, \
+ __FUNCTION__, __LINE__, fmt)
+
+static
+void virInterfaceBareDefFree(virInterfaceBareDefPtr def) {
+ if (def == NULL)
+ return;
+ VIR_FREE(def->name);
+ VIR_FREE(def->mac_or_tag);
+ VIR_FREE(def->devname);
+ VIR_FREE(def);
+}
+
+void virInterfaceDefFree(virInterfaceDefPtr def)
+{
+ int i;
+
+ if (def == NULL)
+ return;
+
+ VIR_FREE(def->name);
+ VIR_FREE(def->mac);
+
+ switch (def->type) {
+ case VIR_INTERFACE_TYPE_BRIDGE:
+ for (i = 0;i < def->data.bridge.nbItf;i++) {
+ if (def->data.bridge.itf[i] != NULL)
+ virInterfaceBareDefFree(def->data.bridge.itf[i]);
+ else
+ break; /* to cope with half parsed data on errors */
+ }
+ VIR_FREE(def->data.bridge.itf);
+ break;
+ case VIR_INTERFACE_TYPE_BOND:
+ VIR_FREE(def->data.bond.target);
+ for (i = 0;i < def->data.bond.nbItf;i++) {
+ if (def->data.bond.itf[i] != NULL)
+ virInterfaceBareDefFree(def->data.bond.itf[i]);
+ else
+ break; /* to cope with half parsed data on errors */
+ }
+ VIR_FREE(def->data.bond.itf);
+ break;
+ case VIR_INTERFACE_TYPE_VLAN:
+ VIR_FREE(def->data.vlan.tag);
+ VIR_FREE(def->data.vlan.devname);
+ break;
+ }
+
+ VIR_FREE(def->proto.family);
+ VIR_FREE(def->proto.address);
+ VIR_FREE(def->proto.gateway);
+
+ VIR_FREE(def);
+}
+
+static int
+virInterfaceDefParseBasicAttrs(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlXPathContextPtr ctxt) {
+ char *tmp;
+ unsigned long mtu;
+ int ret;
+
+ tmp = virXPathString(conn, "string(./@name)", ctxt);
+ if (tmp == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("interface has no name"));
+ return(-1);
+ }
+ def->name = tmp;
+
+ ret = virXPathULong(conn, "string(./mtu/@size)", ctxt, &mtu);
+ if ((ret == -2) || ((ret == 0) && (mtu > 100000))) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("interface mtu value is improper"));
+ return(-1);
+ } else if (ret == 0) {
+ def->mtu = (unsigned int) mtu;
+ }
+ return(0);
+}
+
+static int
+virInterfaceDefParseStartMode(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlXPathContextPtr ctxt) {
+ char *tmp;
+
+ tmp = virXPathString(conn, "string(./start/@mode)", ctxt);
+ if (tmp == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("interface misses the start mode attribute"));
+ return(-1);
+ }
+ if (STREQ(tmp, "onboot"))
+ def->startmode = VIR_INTERFACE_START_ONBOOT;
+ else if (STREQ(tmp, "hotplug"))
+ def->startmode = VIR_INTERFACE_START_HOTPLUG;
+ else if (STREQ(tmp, "none"))
+ def->startmode = VIR_INTERFACE_START_NONE;
+ else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("unknown interface startmode %s"), tmp);
+ VIR_FREE(tmp);
+ return(-1);
+ }
+ VIR_FREE(tmp);
+ return(0);
+}
+
+static int
+virInterfaceDefParseBondMode(virConnectPtr conn, xmlXPathContextPtr ctxt) {
+ char *tmp;
+ int ret = 0;
+
+ tmp = virXPathString(conn, "string(./@mode)", ctxt);
+ if (tmp == NULL)
+ return(VIR_INTERFACE_BOND_NONE);
+ if (STREQ(tmp, "balance-rr"))
+ ret = VIR_INTERFACE_BOND_BALRR;
+ else if (STREQ(tmp, "active-backup"))
+ ret = VIR_INTERFACE_BOND_ABACKUP;
+ else if (STREQ(tmp, "balance-xor"))
+ ret = VIR_INTERFACE_BOND_BALXOR;
+ else if (STREQ(tmp, "broadcast"))
+ ret = VIR_INTERFACE_BOND_BCAST;
+ else if (STREQ(tmp, "802.3ad"))
+ ret = VIR_INTERFACE_BOND_8023AD;
+ else if (STREQ(tmp, "balance-tlb"))
+ ret = VIR_INTERFACE_BOND_BALTLB;
+ else if (STREQ(tmp, "balance-alb"))
+ ret = VIR_INTERFACE_BOND_BALALB;
+ else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("unknown bonding mode %s"), tmp);
+ ret = -1;
+ }
+ VIR_FREE(tmp);
+ return(ret);
+}
+
+static int
+virInterfaceDefParseBondMiiCarrier(virConnectPtr conn, xmlXPathContextPtr ctxt) {
+ char *tmp;
+ int ret = 0;
+
+ tmp = virXPathString(conn, "string(./miimon/@carrier)", ctxt);
+ if (tmp == NULL)
+ return(VIR_INTERFACE_BOND_MII_NONE);
+ if (STREQ(tmp, "ioctl"))
+ ret = VIR_INTERFACE_BOND_MII_IOCTL;
+ else if (STREQ(tmp, "netif"))
+ ret = VIR_INTERFACE_BOND_MII_NETIF;
+ else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("unknown mii bonding carrier %s"), tmp);
+ ret = -1;
+ }
+ VIR_FREE(tmp);
+ return(ret);
+}
+
+static int
+virInterfaceDefParseBondArpValid(virConnectPtr conn, xmlXPathContextPtr ctxt) {
+ char *tmp;
+ int ret = 0;
+
+ tmp = virXPathString(conn, "string(./arpmon/@validate)", ctxt);
+ if (tmp == NULL)
+ return(VIR_INTERFACE_BOND_ARP_NONE);
+ if (STREQ(tmp, "active"))
+ ret = VIR_INTERFACE_BOND_ARP_ACTIVE;
+ else if (STREQ(tmp, "backup"))
+ ret = VIR_INTERFACE_BOND_ARP_BACKUP;
+ else if (STREQ(tmp, "all"))
+ ret = VIR_INTERFACE_BOND_ARP_ALL;
+ else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("unknown arp bonding validate %s"), tmp);
+ ret = -1;
+ }
+ VIR_FREE(tmp);
+ return(ret);
+}
+
+static int
+virInterfaceDefParseDhcp(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlNodePtr dhcp, xmlXPathContextPtr ctxt) {
+ char *tmp;
+ xmlNodePtr old;
+ int ret = 0;
+
+ def->proto.dhcp = 1;
+ old = ctxt->node;
+ ctxt->node = dhcp;
+ /* Not much to do in the current version */
+ tmp = virXPathString(conn, "string(./@peerdns)", ctxt);
+ if (tmp) {
+ if (STREQ(tmp, "yes"))
+ def->proto.peerdns = 1;
+ else if (STREQ(tmp, "no"))
+ def->proto.peerdns = 0;
+ else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("unknown dhcp peerdns value %s"), tmp);
+ ret = -1;
+ }
+ VIR_FREE(tmp);
+ } else
+ def->proto.peerdns = -1;
+
+ return(ret);
+}
+
+static int
+virInterfaceDefParseIp(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlNodePtr ip ATTRIBUTE_UNUSED, xmlXPathContextPtr ctxt) {
+ int ret = 0;
+ char *tmp;
+ long l;
+
+ tmp = virXPathString(conn, "string(./ip[1]/@address)", ctxt);
+ def->proto.address = tmp;
+ if (tmp != NULL) {
+ ret = virXPathLong(conn, "string(./ip[1]/@prefix)", ctxt, &l);
+ if (ret == 0)
+ def->proto.prefix = (int) l;
+ else if (ret == -2) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("Invalid ip address prefix value"));
+ return(-1);
+ }
+ }
+ tmp = virXPathString(conn, "string(./route[1]/@gateway)", ctxt);
+ def->proto.gateway = tmp;
+
+ return(0);
+}
+
+static int
+virInterfaceDefParseProtoIPv4(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlXPathContextPtr ctxt) {
+ xmlNodePtr cur;
+ int ret;
+
+ cur = virXPathNode(conn, "./dhcp", ctxt);
+ if (cur != NULL)
+ ret = virInterfaceDefParseDhcp(conn, def, cur, ctxt);
+ else {
+ cur = virXPathNode(conn, "./ip", ctxt);
+ if (cur != NULL)
+ ret = virInterfaceDefParseIp(conn, def, cur, ctxt);
+ else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("interface miss dhcp or ip adressing"));
+ ret = -1;
+ }
+ }
+ return(ret);
+}
+
+static int
+virInterfaceDefParseIfAdressing(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlXPathContextPtr ctxt) {
+ xmlNodePtr cur, save;
+ int ret;
+ char *tmp;
+
+ cur = virXPathNode(conn, "./protocol[1]", ctxt);
+ if (cur == NULL)
+ return(0);
+ save = ctxt->node;
+ ctxt->node = cur;
+ tmp = virXPathString(conn, "string(./@family)", ctxt);
+ if (tmp == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("protocol misses the family attribute"));
+ ret = -1;
+ goto done;
+ }
+ if (STREQ(tmp, "ipv4")) {
+ def->proto.family = tmp;
+ ret = virInterfaceDefParseProtoIPv4(conn, def, ctxt);
+ } else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("unsupported protocol family '%s'"), tmp);
+ ret = -1;
+ VIR_FREE(tmp);
+ }
+
+done:
+ ctxt->node = save;
+ return(ret);
+
+}
+
+static virInterfaceBareDefPtr
+virInterfaceDefParseBareInterface(virConnectPtr conn, xmlXPathContextPtr ctxt,
+ int ethernet_only) {
+ int t;
+ char *name = NULL;
+ char *type = NULL;
+ char *mac_or_tag = NULL;
+ char *devname = NULL;
+ virInterfaceBareDefPtr ret = NULL;
+
+ type = virXPathString(conn, "string(./@type)", ctxt);
+ if (type == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("interface has no type"));
+ goto error;
+ }
+ if (STREQ(type, "ethernet")) {
+ t = VIR_INTERFACE_TYPE_ETHERNET;
+ name = virXPathString(conn, "string(./@name)", ctxt);
+ mac_or_tag = virXPathString(conn, "string(./mac/@address)", ctxt);
+ } else if ((STREQ(type, "vlan")) && (ethernet_only == 0)) {
+ t = VIR_INTERFACE_TYPE_VLAN;
+ name = virXPathString(conn, "string(./@name)", ctxt);
+ mac_or_tag = virXPathString(conn, "string(./vlan/@tag)", ctxt);
+ devname = virXPathString(conn, "string(./vlan/interface/@name)", ctxt);
+ } else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("interface has unsupported type '%s'"), type);
+ VIR_FREE(type);
+ goto error;
+ }
+ VIR_FREE(type);
+ if (name == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("interface has no name"));
+ goto error;
+ }
+ if (t == VIR_INTERFACE_TYPE_VLAN) {
+ if (mac_or_tag == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("vlan %s has no tag"), name);
+ goto error;
+ }
+ if (devname == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("vlan %s has interface name"), name);
+ goto error;
+ }
+ }
+ if (VIR_ALLOC(ret) < 0) {
+ virReportOOMError(conn);
+ goto error;
+ }
+ ret->type = t;
+ ret->name = name;
+ ret->mac_or_tag = mac_or_tag;
+ ret->devname = devname;
+ return(ret);
+
+error:
+ VIR_FREE(name);
+ VIR_FREE(type);
+ VIR_FREE(name);
+ VIR_FREE(name);
+ VIR_FREE(ret);
+ return(NULL);
+}
+
+static int
+virInterfaceDefParseBridge(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlXPathContextPtr ctxt) {
+ xmlNodePtr *interfaces = NULL;
+ xmlNodePtr bridge;
+ virInterfaceBareDefPtr itf;
+ int nbItf, i;
+ int ret = 0;
+
+ bridge = ctxt->node;
+ nbItf = virXPathNodeSet(conn, "./interface", ctxt, &interfaces);
+ if (nbItf <= 0) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bridge has no interfaces"));
+ ret = -1;
+ goto error;
+ }
+ if (VIR_ALLOC_N(def->data.bridge.itf, nbItf) < 0) {
+ virReportOOMError(conn);
+ ret = -1;
+ goto error;
+ }
+ def->data.bridge.nbItf = nbItf;
+
+ for (i = 0; i < nbItf;i++) {
+ ctxt->node = interfaces[i];
+ itf = virInterfaceDefParseBareInterface(conn, ctxt, 0);
+ if (itf == NULL) {
+ ret = -1;
+ def->data.bridge.nbItf = i;
+ goto error;
+ }
+ def->data.bridge.itf[i] = itf;
+ }
+
+error:
+ VIR_FREE(interfaces);
+ ctxt->node = bridge;
+ return(ret);
+}
+
+static int
+virInterfaceDefParseBondItfs(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlXPathContextPtr ctxt) {
+ xmlNodePtr *interfaces = NULL;
+ xmlNodePtr bond = ctxt->node;
+ virInterfaceBareDefPtr itf;
+ int nbItf, i;
+ int ret = 0;
+
+ nbItf = virXPathNodeSet(conn, "./interface", ctxt, &interfaces);
+ if (nbItf <= 0) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bond has no interfaces"));
+ ret = -1;
+ goto error;
+ }
+ if (VIR_ALLOC_N(def->data.bond.itf, nbItf) < 0) {
+ virReportOOMError(conn);
+ ret = -1;
+ goto error;
+ }
+ def->data.bond.nbItf = nbItf;
+
+ for (i = 0; i < nbItf;i++) {
+ ctxt->node = interfaces[i];
+ itf = virInterfaceDefParseBareInterface(conn, ctxt, 1);
+ if (itf == NULL) {
+ ret = -1;
+ def->data.bond.nbItf = i;
+ goto error;
+ }
+ def->data.bond.itf[i] = itf;
+ }
+
+error:
+ VIR_FREE(interfaces);
+ ctxt->node = bond;
+ return(ret);
+}
+
+static int
+virInterfaceDefParseBond(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlXPathContextPtr ctxt) {
+ xmlNodePtr node;
+ int ret = 0;
+ unsigned long tmp;
+
+ def->data.bond.mode = virInterfaceDefParseBondMode(conn, ctxt);
+ if (def->data.bond.mode < 0)
+ goto error;
+
+ node = virXPathNode(conn, "./miimon[1]", ctxt);
+ if (node != NULL) {
+ def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII;
+
+ ret = virXPathULong(conn, "string(./miimon/@freq)", ctxt, &tmp);
+ if ((ret == -2) || (ret == -1)) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bond interface miimon freq missing or invalid"));
+ goto error;
+ }
+ def->data.bond.frequency = (int) tmp;
+
+ ret = virXPathULong(conn, "string(./miimon/@downdelay)", ctxt, &tmp);
+ if (ret == -2) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bond interface miimon downdelay invalid"));
+ goto error;
+ } else if (ret == 0) {
+ def->data.bond.downdelay = (int) tmp;
+ }
+
+ ret = virXPathULong(conn, "string(./miimon/@updelay)", ctxt, &tmp);
+ if (ret == -2) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bond interface miimon updelay invalid"));
+ goto error;
+ } else if (ret == 0) {
+ def->data.bond.updelay = (int) tmp;
+ }
+
+ def->data.bond.carrier = virInterfaceDefParseBondMiiCarrier(conn, ctxt);
+ if (def->data.bond.carrier < 0)
+ goto error;
+
+ ret = virInterfaceDefParseBondItfs(conn, def, ctxt);
+
+ goto done;
+ }
+ node = virXPathNode(conn, "./arpmon[1]", ctxt);
+ if (node != NULL) {
+ def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP;
+
+ ret = virXPathULong(conn, "string(./arpmon/@interval)", ctxt, &tmp);
+ if ((ret == -2) || (ret == -1)) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bond interface arpmon interval missing or invalid"));
+ goto error;
+ }
+ def->data.bond.interval = (int) tmp;
+
+ def->data.bond.target =
+ virXPathString(conn, "string(./arpmon/@target)", ctxt);
+ if (def->data.bond.target == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bond interface arpmon target missing"));
+ goto error;
+ }
+
+ def->data.bond.validate = virInterfaceDefParseBondArpValid(conn, ctxt);
+ if (def->data.bond.validate < 0)
+ goto error;
+
+ ret = virInterfaceDefParseBondItfs(conn, def, ctxt);
+
+ goto done;
+ }
+
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bond interface need miimon or arpmon element"));
+error:
+ ret = -1;
+done:
+ return(ret);
+}
+
+static int
+virInterfaceDefParseVlan(virConnectPtr conn, virInterfaceDefPtr def,
+ xmlXPathContextPtr ctxt) {
+ def->data.vlan.tag = virXPathString(conn, "string(./@tag)", ctxt);
+ if (def->data.vlan.tag == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("vlan interface misses the tag attribute"));
+ return(-1);
+ }
+
+ def->data.vlan.devname =
+ virXPathString(conn, "string(./interface/@name)", ctxt);
+ if (def->data.vlan.devname == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("vlan interface misses name attribute"));
+ return(-1);
+ }
+ return(0);
+}
+
+static virInterfaceDefPtr
+virInterfaceDefParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt) {
+ virInterfaceDefPtr def;
+ int type;
+ char *tmp;
+ xmlNodePtr cur = ctxt->node;
+
+ /* check @type */
+ tmp = virXPathString(conn, "string(./@type)", ctxt);
+ if (tmp == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("interface misses the type attribute"));
+ return(NULL);
+ }
+ type = virInterfaceTypeFromString(tmp);
+ if (type == -1) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("unknown interface type %s"), tmp);
+ VIR_FREE(tmp);
+ return(NULL);
+ }
+ VIR_FREE(tmp);
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+ def->type = type;
+ switch (type) {
+ case VIR_INTERFACE_TYPE_ETHERNET:
+ if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0)
+ goto error;
+ tmp = virXPathString(conn, "string(./mac/@address)", ctxt);
+ if (tmp != NULL)
+ def->mac = tmp;
+ if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0)
+ goto error;
+ if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0)
+ goto error;
+ break;
+ case VIR_INTERFACE_TYPE_BRIDGE: {
+ xmlNodePtr bridge;
+
+ if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0)
+ goto error;
+ if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0)
+ goto error;
+ if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0)
+ goto error;
+
+ bridge = virXPathNode(conn, "./bridge[1]", ctxt);
+ if (bridge == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("bridge interface misses the bridge element"));
+ goto error;
+ }
+ tmp = virXMLPropString(bridge, "stp");
+ def->data.bridge.stp = -1;
+ if (tmp != NULL) {
+ if (STREQ(tmp, "on")) {
+ def->data.bridge.stp = 1;
+ } else if (STREQ(tmp, "off")) {
+ def->data.bridge.stp = 0;
+ } else {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ _("bridge interface stp should be on or off got %s"),
+ tmp);
+ VIR_FREE(tmp);
+ goto error;
+ }
+ VIR_FREE(tmp);
+ }
+ ctxt->node = bridge;
+ virInterfaceDefParseBridge(conn, def, ctxt);
+ break;
+ }
+ case VIR_INTERFACE_TYPE_BOND: {
+ xmlNodePtr bond;
+
+ if (virInterfaceDefParseBasicAttrs(conn, def, ctxt) < 0)
+ goto error;
+ if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0)
+ goto error;
+ if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0)
+ goto error;
+ bond = virXPathNode(conn, "./bond[1]", ctxt);
+ if (bond == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("bond interface misses the bond element"));
+ goto error;
+ }
+ ctxt->node = bond;
+ if (virInterfaceDefParseBond(conn, def, ctxt) < 0)
+ goto error;
+ break;
+ }
+ case VIR_INTERFACE_TYPE_VLAN: {
+ xmlNodePtr vlan;
+
+ tmp = virXPathString(conn, "string(./@name)", ctxt);
+ if (tmp != NULL)
+ def->name = tmp;
+ if (virInterfaceDefParseStartMode(conn, def, ctxt) < 0)
+ goto error;
+ if (virInterfaceDefParseIfAdressing(conn, def, ctxt) < 0)
+ goto error;
+ vlan = virXPathNode(conn, "./vlan[1]", ctxt);
+ if (vlan == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("vlan interface misses the vlan element"));
+ goto error;
+ }
+ ctxt->node = vlan;
+ if (virInterfaceDefParseVlan(conn, def, ctxt) < 0)
+ goto error;
+ break;
+ }
+
+ }
+
+ ctxt->node = cur;
+ return def;
+
+error:
+ ctxt->node = cur;
+ virInterfaceDefFree(def);
+ return NULL;
+}
+
+virInterfaceDefPtr virInterfaceDefParseNode(virConnectPtr conn,
+ xmlDocPtr xml,
+ xmlNodePtr root)
+{
+ xmlXPathContextPtr ctxt = NULL;
+ virInterfaceDefPtr def = NULL;
+
+ if (!xmlStrEqual(root->name, BAD_CAST "interface")) {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("incorrect root element"));
+ return NULL;
+ }
+
+ ctxt = xmlXPathNewContext(xml);
+ if (ctxt == NULL) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+
+ ctxt->node = root;
+ def = virInterfaceDefParseXML(conn, ctxt);
+
+cleanup:
+ xmlXPathFreeContext(ctxt);
+ return def;
+}
+
+/* Called from SAX on parsing errors in the XML. */
+static void
+catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+
+ if (ctxt) {
+ virConnectPtr conn = ctxt->_private;
+
+ if (conn &&
+ conn->err.code == VIR_ERR_NONE &&
+ ctxt->lastError.level == XML_ERR_FATAL &&
+ ctxt->lastError.message != NULL) {
+ virInterfaceReportError (conn, VIR_ERR_XML_DETAIL,
+ _("at line %d: %s"),
+ ctxt->lastError.line,
+ ctxt->lastError.message);
+ }
+ }
+}
+
+virInterfaceDefPtr virInterfaceDefParseString(virConnectPtr conn,
+ const char *xmlStr)
+{
+ xmlParserCtxtPtr pctxt;
+ xmlDocPtr xml = NULL;
+ xmlNodePtr root;
+ virInterfaceDefPtr def = NULL;
+
+ /* Set up a parser context so we can catch the details of XML errors. */
+ pctxt = xmlNewParserCtxt ();
+ if (!pctxt || !pctxt->sax)
+ goto cleanup;
+ pctxt->sax->error = catchXMLError;
+ pctxt->_private = conn;
+
+ if (conn) virResetError (&conn->err);
+ xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "interface.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ if (!xml) {
+ if (conn && conn->err.code == VIR_ERR_NONE)
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("failed to parse xml document"));
+ goto cleanup;
+ }
+
+ if ((root = xmlDocGetRootElement(xml)) == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing root element"));
+ goto cleanup;
+ }
+
+ def = virInterfaceDefParseNode(conn, xml, root);
+
+cleanup:
+ xmlFreeParserCtxt (pctxt);
+ xmlFreeDoc (xml);
+ return def;
+}
+
+virInterfaceDefPtr virInterfaceDefParseFile(virConnectPtr conn,
+ const char *filename)
+{
+ xmlParserCtxtPtr pctxt;
+ xmlDocPtr xml = NULL;
+ xmlNodePtr root;
+ virInterfaceDefPtr def = NULL;
+
+ /* Set up a parser context so we can catch the details of XML errors. */
+ pctxt = xmlNewParserCtxt ();
+ if (!pctxt || !pctxt->sax)
+ goto cleanup;
+ pctxt->sax->error = catchXMLError;
+ pctxt->_private = conn;
+
+ if (conn) virResetError (&conn->err);
+ xml = xmlCtxtReadFile (pctxt, filename, NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ if (!xml) {
+ if (conn && conn->err.code == VIR_ERR_NONE)
+ virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("failed to parse xml document"));
+ goto cleanup;
+ }
+
+ if ((root = xmlDocGetRootElement(xml)) == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing root element"));
+ goto cleanup;
+ }
+
+ def = virInterfaceDefParseNode(conn, xml, root);
+
+cleanup:
+ xmlFreeParserCtxt (pctxt);
+ xmlFreeDoc (xml);
+ return def;
+}
+
+static int
+virInterfaceBareDevDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virBufferPtr buf,
+ const virInterfaceBareDefPtr def) {
+ if (def->type == VIR_INTERFACE_TYPE_ETHERNET) {
+ if (def->name == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("bare ethernet has no name"));
+ return(-1);
+ }
+ virBufferVSprintf(buf, " <interface type='ethernet' name='%s'",
+ def->name);
+ if (def->mac_or_tag != NULL) {
+ virBufferVSprintf(buf, ">\n <mac address='%s'/>\n",
+ def->mac_or_tag);
+ virBufferAddLit(buf, " </interface>\n");
+ } else {
+ virBufferAddLit(buf, "/>\n");
+ }
+ } else if (def->type == VIR_INTERFACE_TYPE_VLAN) {
+ virBufferAddLit(buf, " <interface type='vlan'");
+ if (def->name != NULL)
+ virBufferVSprintf(buf, " name='%s'", def->name);
+ if (def->mac_or_tag != NULL) {
+ virBufferAddLit(buf, ">\n");
+ virBufferVSprintf(buf, " <vlan tag='%s'", def->mac_or_tag);
+ if (def->devname != NULL) {
+ virBufferAddLit(buf, ">\n");
+ virBufferVSprintf(buf, " <interface name='%s'/>\n",
+ def->devname);
+ virBufferAddLit(buf, " </vlan>\n");
+ } else
+ virBufferAddLit(buf, "/>\n");
+ virBufferAddLit(buf, " </interface>\n");
+ } else {
+ virBufferAddLit(buf, "/>\n");
+ }
+ } else {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("bare interface type %d unknown"),
+ def->type);
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+virInterfaceBridgeDefFormat(virConnectPtr conn, virBufferPtr buf,
+ const virInterfaceDefPtr def) {
+ int i;
+ int ret = 0;
+
+ if (def->data.bridge.stp == 1)
+ virBufferAddLit(buf, " <bridge stp='on'>\n");
+ else if (def->data.bridge.stp == 0)
+ virBufferAddLit(buf, " <bridge stp='off'>\n");
+ else
+ virBufferAddLit(buf, " <bridge>\n");
+
+ for (i = 0;i < def->data.bridge.nbItf;i++) {
+ if (virInterfaceBareDevDefFormat(conn, buf, def->data.bridge.itf[i])
+ < 0)
+ ret = -1;
+ }
+
+ virBufferAddLit(buf, " </bridge>\n");
+ return(ret);
+}
+
+static int
+virInterfaceBondDefFormat(virConnectPtr conn, virBufferPtr buf,
+ const virInterfaceDefPtr def) {
+ int i;
+ int ret = 0;
+
+ virBufferAddLit(buf, " <bond");
+ if (def->data.bond.mode == VIR_INTERFACE_BOND_BALRR)
+ virBufferAddLit(buf, " mode='balance-rr'");
+ else if (def->data.bond.mode == VIR_INTERFACE_BOND_ABACKUP)
+ virBufferAddLit(buf, " mode='active-backup'");
+ else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALXOR)
+ virBufferAddLit(buf, " mode='balance-xor'");
+ else if (def->data.bond.mode == VIR_INTERFACE_BOND_BCAST)
+ virBufferAddLit(buf, " mode='broadcast'");
+ else if (def->data.bond.mode == VIR_INTERFACE_BOND_8023AD)
+ virBufferAddLit(buf, " mode='802.3ad'");
+ else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALTLB)
+ virBufferAddLit(buf, " mode='balance-tlb'");
+ else if (def->data.bond.mode == VIR_INTERFACE_BOND_BALALB)
+ virBufferAddLit(buf, " mode='balance-alb'");
+ virBufferAddLit(buf, ">\n");
+
+ if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_MII) {
+ virBufferVSprintf(buf, " <miimon freq='%d'",
+ def->data.bond.frequency);
+ if (def->data.bond.downdelay > 0)
+ virBufferVSprintf(buf, " downdelay='%d'", def->data.bond.downdelay);
+ if (def->data.bond.updelay > 0)
+ virBufferVSprintf(buf, " updelay='%d'", def->data.bond.updelay);
+ if (def->data.bond.carrier == VIR_INTERFACE_BOND_MII_IOCTL)
+ virBufferAddLit(buf, " carrier='ioctl'");
+ else if (def->data.bond.carrier == VIR_INTERFACE_BOND_MII_NETIF)
+ virBufferAddLit(buf, " carrier='netif'");
+ virBufferAddLit(buf, "/>\n");
+ } else if (def->data.bond.monit == VIR_INTERFACE_BOND_MONIT_ARP) {
+ if (def->data.bond.target == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("bond arp monitoring has no target"));
+ return(-1);
+ }
+ virBufferVSprintf(buf, " <arpmon interval='%d' target='%s'",
+ def->data.bond.interval, def->data.bond.target);
+ if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ACTIVE)
+ virBufferAddLit(buf, " validate='active'");
+ else if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_BACKUP)
+ virBufferAddLit(buf, " validate='backup'");
+ else if (def->data.bond.validate == VIR_INTERFACE_BOND_ARP_ALL)
+ virBufferAddLit(buf, " validate='all'");
+ virBufferAddLit(buf, "/>\n");
+ } else {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("bond monitoring type %d unknown"),
+ def->data.bond.monit);
+ return(-1);
+ }
+ for (i = 0;i < def->data.bond.nbItf;i++) {
+ if (virInterfaceBareDevDefFormat(conn, buf, def->data.bond.itf[i]) < 0)
+ ret = -1;
+ }
+
+ virBufferAddLit(buf, " </bond>\n");
+ return(ret);
+}
+
+static int
+virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf,
+ const virInterfaceDefPtr def) {
+ if (def->data.vlan.tag == NULL) {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("vlan misses the tag name"));
+ return(-1);
+ }
+
+ virBufferVSprintf(buf, " <vlan tag='%s'", def->data.vlan.tag);
+ if (def->data.vlan.devname != NULL) {
+ virBufferAddLit(buf, ">\n");
+ virBufferVSprintf(buf, " <interface name='%s'/>\n",
+ def->data.vlan.devname);
+ virBufferAddLit(buf, " </vlan>\n");
+ } else
+ virBufferAddLit(buf, "/>\n");
+ return(0);
+}
+
+static int
+virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virBufferPtr buf, const virInterfaceDefPtr def) {
+ if (def->proto.family == NULL)
+ return(0);
+ virBufferVSprintf(buf, " <protocol family='%s'>\n", def->proto.family);
+ if (def->proto.dhcp) {
+ if (def->proto.peerdns == 0)
+ virBufferAddLit(buf, " <dhcp peerdns='no'/>\n");
+ else if (def->proto.peerdns == 1)
+ virBufferAddLit(buf, " <dhcp peerdns='yes'/>\n");
+ else
+ virBufferAddLit(buf, " <dhcp/>\n");
+ } else {
+ /* theorically if we don't have dhcp we should have an address */
+ if (def->proto.address != NULL) {
+ if (def->proto.prefix != 0)
+ virBufferVSprintf(buf, " <ip address='%s' prefix='%d'/>\n",
+ def->proto.address, def->proto.prefix);
+ else
+ virBufferVSprintf(buf, " <ip address='%s'/>\n",
+ def->proto.address);
+ }
+ if (def->proto.gateway != NULL) {
+ virBufferVSprintf(buf, " <route gateway='%s'/>\n",
+ def->proto.gateway);
+ }
+ }
+ virBufferAddLit(buf, " </protocol>\n");
+ return(0);
+}
+
+static int
+virInterfaceStartmodeDefFormat(virConnectPtr conn, virBufferPtr buf,
+ enum virInterfaceStartMode startmode) {
+ const char *mode;
+ switch (startmode) {
+ case VIR_INTERFACE_START_NONE:
+ mode = "none";
+ break;
+ case VIR_INTERFACE_START_ONBOOT:
+ mode = "onboot";
+ break;
+ case VIR_INTERFACE_START_HOTPLUG:
+ mode = "hotplug";
+ break;
+ default:
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("virInterfaceDefFormat unknown startmode"));
+ return -1;
+ }
+ virBufferVSprintf(buf, " <start mode='%s'/>\n", mode);
+ return(0);
+}
+
+char *virInterfaceDefFormat(virConnectPtr conn,
+ const virInterfaceDefPtr def)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ const char *type = NULL, *tmp;
+
+ if ((def == NULL) ||
+ ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN))) {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("virInterfaceDefFormat argument problems"));
+ goto cleanup;
+ }
+
+ if (!(type = virInterfaceTypeToString(def->type))) {
+ virInterfaceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("unexpected interface type %d"), def->type);
+ goto cleanup;
+ }
+
+ virBufferVSprintf(&buf, "<interface type='%s' ", type);
+ if (def->name != NULL)
+ virBufferEscapeString(&buf, "name='%s'", def->name);
+ virBufferAddLit(&buf, ">\n");
+
+ switch (def->type) {
+ case VIR_INTERFACE_TYPE_ETHERNET:
+ virInterfaceStartmodeDefFormat(conn, &buf, def->startmode);
+ if (def->mac != NULL)
+ virBufferVSprintf(&buf, " <mac address='%s'/>\n", def->mac);
+ if (def->mtu != 0)
+ virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu);
+ virInterfaceProtocolDefFormat(conn, &buf, def);
+ break;
+ case VIR_INTERFACE_TYPE_BRIDGE:
+ virInterfaceStartmodeDefFormat(conn, &buf, def->startmode);
+ if (def->mtu != 0)
+ virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu);
+ virInterfaceProtocolDefFormat(conn, &buf, def);
+ virInterfaceBridgeDefFormat(conn, &buf, def);
+ break;
+ case VIR_INTERFACE_TYPE_BOND:
+ virInterfaceStartmodeDefFormat(conn, &buf, def->startmode);
+ if (def->mtu != 0)
+ virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu);
+ virInterfaceProtocolDefFormat(conn, &buf, def);
+ virInterfaceBondDefFormat(conn, &buf, def);
+ break;
+ case VIR_INTERFACE_TYPE_VLAN:
+ virInterfaceStartmodeDefFormat(conn, &buf, def->startmode);
+ if (def->mac != NULL)
+ virBufferVSprintf(&buf, " <mac address='%s'/>\n", def->mac);
+ if (def->mtu != 0)
+ virBufferVSprintf(&buf, " <mtu size='%d'/>\n", def->mtu);
+ virInterfaceProtocolDefFormat(conn, &buf, def);
+ virInterfaceVlanDefFormat(conn, &buf, def);
+ break;
+ }
+
+ virBufferAddLit(&buf, "</interface>\n");
+
+ if (virBufferError(&buf))
+ goto no_memory;
+ return virBufferContentAndReset(&buf);
+
+no_memory:
+ virReportOOMError(conn);
+cleanup:
+ tmp = virBufferContentAndReset(&buf);
+ VIR_FREE(tmp);
+ return NULL;
+}
+
+void virInterfaceObjLock(virInterfaceObjPtr obj)
+{
+ virMutexLock(&obj->lock);
+}
+
+void virInterfaceObjUnlock(virInterfaceObjPtr obj)
+{
+ virMutexUnlock(&obj->lock);
+}
--- /dev/null
+/*
+ * interface_conf.h: interface XML handling entry points
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ *
+ * 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 Veillard <veillard@redhat.com>
+ * Laine Stump <laine@redhat.com>
+ */
+
+#ifndef __INTERFACE_CONF_H__
+#define __INTERFACE_CONF_H__
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+#include "internal.h"
+#include "util.h"
+#include "threads.h"
+
+/* There is currently 3 types of interfaces */
+
+enum virInterfaceType {
+ VIR_INTERFACE_TYPE_ETHERNET, /* simple ethernet */
+ VIR_INTERFACE_TYPE_BRIDGE, /* bridge interface */
+ VIR_INTERFACE_TYPE_BOND, /* bonding interface */
+ VIR_INTERFACE_TYPE_VLAN, /* vlan description */
+
+ VIR_INTERFACE_TYPE_LAST,
+};
+
+VIR_ENUM_DECL(virInterface)
+
+/* types of start mode */
+
+enum virInterfaceStartMode {
+ VIR_INTERFACE_START_NONE = 0, /* not defined */
+ VIR_INTERFACE_START_ONBOOT, /* startup at boot */
+ VIR_INTERFACE_START_HOTPLUG, /* on hotplug */
+};
+
+enum virInterfaceBondMode {
+ VIR_INTERFACE_BOND_NONE = 0,
+ VIR_INTERFACE_BOND_BALRR, /* balance-rr */
+ VIR_INTERFACE_BOND_ABACKUP, /* active backup */
+ VIR_INTERFACE_BOND_BALXOR, /* balance-xor */
+ VIR_INTERFACE_BOND_BCAST, /* broadcast */
+ VIR_INTERFACE_BOND_8023AD, /* 802.3ad */
+ VIR_INTERFACE_BOND_BALTLB, /* balance-tlb */
+ VIR_INTERFACE_BOND_BALALB, /* balance-alb */
+};
+
+enum virInterfaceBondMonit {
+ VIR_INTERFACE_BOND_MONIT_NONE = 0,
+ VIR_INTERFACE_BOND_MONIT_MII, /* mii based monitoring */
+ VIR_INTERFACE_BOND_MONIT_ARP, /* arp based monitoring */
+};
+
+enum virInterfaceBondMiiCarrier {
+ VIR_INTERFACE_BOND_MII_NONE = 0,
+ VIR_INTERFACE_BOND_MII_IOCTL, /* mii/ethtool ioctl */
+ VIR_INTERFACE_BOND_MII_NETIF, /* netif_carrier_ok */
+};
+
+enum virInterfaceBondArpValid {
+ VIR_INTERFACE_BOND_ARP_NONE = 0,
+ VIR_INTERFACE_BOND_ARP_ACTIVE, /* validate active */
+ VIR_INTERFACE_BOND_ARP_BACKUP, /* validate backup */
+ VIR_INTERFACE_BOND_ARP_ALL, /* validate all */
+};
+
+typedef struct _virInterfaceBareDef virInterfaceBareDef;
+typedef virInterfaceBareDef *virInterfaceBareDefPtr;
+struct _virInterfaceBareDef {
+ int type; /* should be only ethernet or vlan */
+ char *name; /* the interface name */
+ char *mac_or_tag; /* MAC address for ethernet, TAG for vlan */
+ char *devname; /* device name for vlan */
+};
+
+typedef struct _virInterfaceBridgeDef virInterfaceBridgeDef;
+typedef virInterfaceBridgeDef *virInterfaceBridgeDefPtr;
+struct _virInterfaceBridgeDef {
+ int stp; /* 0, 1 or -1 if undefined */
+ int nbItf; /* number of defined interfaces */
+ virInterfaceBareDefPtr *itf;/* interfaces */
+};
+
+typedef struct _virInterfaceBondDef virInterfaceBondDef;
+typedef virInterfaceBondDef *virInterfaceBondDefPtr;
+struct _virInterfaceBondDef {
+ int mode; /* virInterfaceBondMode */
+ int monit; /* virInterfaceBondMonit */
+ int frequency; /* miimon frequency in ms */
+ int downdelay; /* miimon downdelay */
+ int updelay; /* miimon updelay */
+ int carrier; /* virInterfaceBondMiiCarrier */
+ int interval; /* arp monitoring interval */
+ char *target; /* arp monitoring target */
+ int validate; /* virInterfaceBondArpmValid */
+ int nbItf; /* number of defined interfaces */
+ virInterfaceBareDefPtr *itf; /* interfaces ethernet only */
+};
+
+typedef struct _virInterfaceVlanDef virInterfaceVlanDef;
+typedef virInterfaceVlanDef *virInterfaceVlanDefPtr;
+struct _virInterfaceVlanDef {
+ char *tag; /* TAG for vlan */
+ char *devname; /* device name for vlan */
+};
+
+typedef struct _virInterfaceProtocolDef virInterfaceProtocolDef;
+typedef virInterfaceProtocolDef *virInterfaceProtocolDefPtr;
+struct _virInterfaceProtocolDef {
+ char *family; /* ipv4 only right now */
+ int dhcp; /* use dhcp */
+ int peerdns; /* dhcp peerdns ? */
+ char *address; /* ip address */
+ int prefix; /* ip prefix */
+ char *gateway; /* route gateway */
+};
+
+
+typedef struct _virInterfaceDef virInterfaceDef;
+typedef virInterfaceDef *virInterfaceDefPtr;
+struct _virInterfaceDef {
+ int type; /* interface type */
+ char *name; /* interface name */
+ unsigned int mtu; /* maximum transmit size in byte */
+ char *mac; /* MAC address */
+
+ enum virInterfaceStartMode startmode; /* how it is started */
+
+ union {
+ virInterfaceBridgeDef bridge;
+ virInterfaceVlanDef vlan;
+ virInterfaceBondDef bond;
+ } data;
+
+ /* separated as we may allow multiple of those in the future */
+ virInterfaceProtocolDef proto;
+};
+
+typedef struct _virInterfaceObj virInterfaceObj;
+typedef virInterfaceObj *virInterfaceObjPtr;
+struct _virInterfaceObj {
+ virMutex lock;
+
+ virInterfaceDefPtr def; /* The interface definition */
+};
+
+typedef struct _virInterfaceObjList virInterfaceObjList;
+typedef virInterfaceObjList *virInterfaceObjListPtr;
+struct _virInterfaceObjList {
+ unsigned int count;
+ virInterfaceObjPtr *objs;
+};
+
+virInterfaceObjPtr virInterfaceFindByMACString(const virInterfaceObjListPtr interfaces,
+ const char *mac);
+virInterfaceObjPtr virInterfaceFindByName(const virInterfaceObjListPtr interfaces,
+ const char *name);
+
+
+void virInterfaceDefFree(virInterfaceDefPtr def);
+void virInterfaceObjFree(virInterfaceObjPtr interface);
+void virInterfaceObjListFree(virInterfaceObjListPtr vms);
+
+virInterfaceObjPtr virInterfaceAssignDef(virConnectPtr conn,
+ virInterfaceObjListPtr interfaces,
+ const virInterfaceDefPtr def);
+void virInterfaceRemove(virInterfaceObjListPtr interfaces,
+ const virInterfaceObjPtr interface);
+
+virInterfaceDefPtr virInterfaceDefParseString(virConnectPtr conn,
+ const char *xmlStr);
+virInterfaceDefPtr virInterfaceDefParseFile(virConnectPtr conn,
+ const char *filename);
+virInterfaceDefPtr virInterfaceDefParseNode(virConnectPtr conn,
+ xmlDocPtr xml,
+ xmlNodePtr root);
+
+char *virInterfaceDefFormat(virConnectPtr conn,
+ const virInterfaceDefPtr def);
+
+void virInterfaceObjLock(virInterfaceObjPtr obj);
+void virInterfaceObjUnlock(virInterfaceObjPtr obj);
+
+#endif /* __INTERFACE_CONF_H__ */