static int virInterfaceDefParseIp(virInterfaceIpDefPtr def, xmlXPathContextPtr ctxt) { int ret = 0; char *tmp; long l; tmp = virXPathString("string(./@address)", ctxt); def->address = tmp; if (tmp != NULL) { ret = virXPathLong("string(./@prefix)", ctxt, &l); if (ret == 0) def->prefix = (int) l; else if (ret == -2) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("Invalid ip address prefix value")); return -1; } } return 0; }
static int virInterfaceDefParseBondArpValid(xmlXPathContextPtr ctxt) { char *tmp; int ret = 0; tmp = virXPathString("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(VIR_ERR_XML_ERROR, _("unknown arp bonding validate %s"), tmp); ret = -1; } VIR_FREE(tmp); return ret; }
static int virInterfaceDefParseBondItfs(virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr *interfaces = NULL; xmlNodePtr bond = ctxt->node; virInterfaceDefPtr itf; int nbItf, i; int ret = 0; nbItf = virXPathNodeSet("./interface", ctxt, &interfaces); if (nbItf <= 0) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond has no interfaces")); ret = -1; goto error; } if (VIR_ALLOC_N(def->data.bond.itf, nbItf) < 0) { virReportOOMError(); ret = -1; goto error; } def->data.bond.nbItf = nbItf; for (i = 0; i < nbItf;i++) { ctxt->node = interfaces[i]; itf = virInterfaceDefParseXML(ctxt, VIR_INTERFACE_TYPE_BOND); 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 virInterfaceDefParseStartMode(virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { char *tmp; tmp = virXPathString("string(./start/@mode)", ctxt); if (tmp == NULL) def->startmode = VIR_INTERFACE_START_UNSPECIFIED; else 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(VIR_ERR_XML_ERROR, _("unknown interface startmode %s"), tmp); VIR_FREE(tmp); return -1; } VIR_FREE(tmp); return 0; }
virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces, const virInterfaceDefPtr def) { virInterfaceObjPtr iface; if ((iface = virInterfaceFindByName(interfaces, def->name))) { virInterfaceDefFree(iface->def); iface->def = def; return iface; } if (VIR_ALLOC(iface) < 0) { virReportOOMError(); return NULL; } if (virMutexInit(&iface->lock) < 0) { virInterfaceReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize mutex")); VIR_FREE(iface); return NULL; } virInterfaceObjLock(iface); iface->def = def; if (VIR_REALLOC_N(interfaces->objs, interfaces->count + 1) < 0) { virReportOOMError(); VIR_FREE(iface); return NULL; } interfaces->objs[interfaces->count] = iface; interfaces->count++; return iface; }
static virInterfaceDefPtr virInterfaceDefParseXML(xmlXPathContextPtr ctxt, int parentIfType) { virInterfaceDefPtr def; int type; char *tmp; xmlNodePtr cur = ctxt->node; /* check @type */ tmp = virXPathString("string(./@type)", ctxt); if (tmp == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("interface misses the type attribute")); return NULL; } type = virInterfaceTypeFromString(tmp); if (type == -1) { virInterfaceReportError(VIR_ERR_XML_ERROR, _("unknown interface type %s"), tmp); VIR_FREE(tmp); return NULL; } VIR_FREE(tmp); if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } if (((parentIfType == VIR_INTERFACE_TYPE_BOND) && (type != VIR_INTERFACE_TYPE_ETHERNET)) || ((parentIfType == VIR_INTERFACE_TYPE_BRIDGE) && (type != VIR_INTERFACE_TYPE_ETHERNET) && (type != VIR_INTERFACE_TYPE_BOND) && (type != VIR_INTERFACE_TYPE_VLAN)) || (parentIfType == VIR_INTERFACE_TYPE_ETHERNET) || (parentIfType == VIR_INTERFACE_TYPE_VLAN)) { virInterfaceReportError(VIR_ERR_XML_ERROR, _("interface has unsupported type '%s'"), virInterfaceTypeToString(type)); goto error; } def->type = type; switch (type) { case VIR_INTERFACE_TYPE_ETHERNET: if (virInterfaceDefParseName(def, ctxt) < 0) goto error; tmp = virXPathString("string(./mac/@address)", ctxt); if (tmp != NULL) def->mac = tmp; if (parentIfType == VIR_INTERFACE_TYPE_LAST) { /* only recognize these in toplevel bond interfaces */ if (virInterfaceDefParseStartMode(def, ctxt) < 0) goto error; if (virInterfaceDefParseMtu(def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(def, ctxt) < 0) goto error; } break; case VIR_INTERFACE_TYPE_BRIDGE: { xmlNodePtr bridge; if (virInterfaceDefParseName(def, ctxt) < 0) goto error; if (virInterfaceDefParseStartMode(def, ctxt) < 0) goto error; if (virInterfaceDefParseMtu(def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(def, ctxt) < 0) goto error; bridge = virXPathNode("./bridge[1]", ctxt); if (bridge == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("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(VIR_ERR_XML_ERROR, _("bridge interface stp should be on or off got %s"), tmp); VIR_FREE(tmp); goto error; } VIR_FREE(tmp); } def->data.bridge.delay = virXMLPropString(bridge, "delay"); ctxt->node = bridge; virInterfaceDefParseBridge(def, ctxt); break; } case VIR_INTERFACE_TYPE_BOND: { xmlNodePtr bond; if (virInterfaceDefParseName(def, ctxt) < 0) goto error; if (parentIfType == VIR_INTERFACE_TYPE_LAST) { /* only recognize these in toplevel bond interfaces */ if (virInterfaceDefParseStartMode(def, ctxt) < 0) goto error; if (virInterfaceDefParseMtu(def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(def, ctxt) < 0) goto error; } bond = virXPathNode("./bond[1]", ctxt); if (bond == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface misses the bond element")); goto error; } ctxt->node = bond; if (virInterfaceDefParseBond(def, ctxt) < 0) goto error; break; } case VIR_INTERFACE_TYPE_VLAN: { xmlNodePtr vlan; tmp = virXPathString("string(./@name)", ctxt); if (tmp != NULL) def->name = tmp; if (virInterfaceDefParseStartMode(def, ctxt) < 0) goto error; if (virInterfaceDefParseIfAdressing(def, ctxt) < 0) goto error; vlan = virXPathNode("./vlan[1]", ctxt); if (vlan == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("vlan interface misses the vlan element")); goto error; } ctxt->node = vlan; if (virInterfaceDefParseVlan(def, ctxt) < 0) goto error; break; } } ctxt->node = cur; return def; error: ctxt->node = cur; virInterfaceDefFree(def); return NULL; }
static int virInterfaceDefParseBond(virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { int ret = -1; unsigned long tmp; def->data.bond.mode = virInterfaceDefParseBondMode(ctxt); if (def->data.bond.mode < 0) goto error; ret = virInterfaceDefParseBondItfs(def, ctxt); if (ret != 0) goto error; if (virXPathNode("./miimon[1]", ctxt) != NULL) { def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII; ret = virXPathULong("string(./miimon/@freq)", ctxt, &tmp); if ((ret == -2) || (ret == -1)) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface miimon freq missing or invalid")); goto error; } def->data.bond.frequency = (int) tmp; ret = virXPathULong("string(./miimon/@downdelay)", ctxt, &tmp); if (ret == -2) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface miimon downdelay invalid")); goto error; } else if (ret == 0) { def->data.bond.downdelay = (int) tmp; } ret = virXPathULong("string(./miimon/@updelay)", ctxt, &tmp); if (ret == -2) { virInterfaceReportError(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(ctxt); if (def->data.bond.carrier < 0) { ret = -1; goto error; } } else if (virXPathNode("./arpmon[1]", ctxt) != NULL) { def->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP; ret = virXPathULong("string(./arpmon/@interval)", ctxt, &tmp); if ((ret == -2) || (ret == -1)) { virInterfaceReportError(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("string(./arpmon/@target)", ctxt); if (def->data.bond.target == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("bond interface arpmon target missing")); ret = -1; goto error; } def->data.bond.validate = virInterfaceDefParseBondArpValid(ctxt); if (def->data.bond.validate < 0) { ret = -1; goto error; } } error: return ret; }
static int virInterfaceDefParseIfAdressing(virInterfaceDefPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr save; xmlNodePtr *protoNodes = NULL; int nProtoNodes, pp, ret = -1; char *tmp; save = ctxt->node; nProtoNodes = virXPathNodeSet("./protocol", ctxt, &protoNodes); if (nProtoNodes < 0) goto error; if (nProtoNodes == 0) { /* no protocols is an acceptable outcome */ return 0; } if (VIR_ALLOC_N(def->protos, nProtoNodes) < 0) { virReportOOMError(); goto error; } def->nprotos = 0; for (pp = 0; pp < nProtoNodes; pp++) { virInterfaceProtocolDefPtr proto; if (VIR_ALLOC(proto) < 0) { virReportOOMError(); goto error; } ctxt->node = protoNodes[pp]; tmp = virXPathString("string(./@family)", ctxt); if (tmp == NULL) { virInterfaceReportError(VIR_ERR_XML_ERROR, "%s", _("protocol misses the family attribute")); virInterfaceProtocolDefFree(proto); goto error; } proto->family = tmp; if (STREQ(tmp, "ipv4")) { ret = virInterfaceDefParseProtoIPv4(proto, ctxt); if (ret != 0) { virInterfaceProtocolDefFree(proto); goto error; } } else if (STREQ(tmp, "ipv6")) { ret = virInterfaceDefParseProtoIPv6(proto, ctxt); if (ret != 0) { virInterfaceProtocolDefFree(proto); goto error; } } else { virInterfaceReportError(VIR_ERR_XML_ERROR, _("unsupported protocol family '%s'"), tmp); virInterfaceProtocolDefFree(proto); goto error; } def->protos[def->nprotos++] = proto; } ret = 0; error: VIR_FREE(protoNodes); ctxt->node = save; return ret; }
static int virInterfaceDefDevFormat(virBufferPtr buf, const virInterfaceDefPtr def, int level) { const char *type = NULL; if (def == NULL) { virInterfaceReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("virInterfaceDefFormat NULL def")); goto cleanup; } if ((def->name == NULL) && (def->type != VIR_INTERFACE_TYPE_VLAN)) { virInterfaceReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("virInterfaceDefFormat missing interface name")); goto cleanup; } if (!(type = virInterfaceTypeToString(def->type))) { virInterfaceReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected interface type %d"), def->type); goto cleanup; } virBufferAsprintf(buf, "%*s<interface type='%s' ", level*2, "", type); if (def->name != NULL) virBufferEscapeString(buf, "name='%s'", def->name); virBufferAddLit(buf, ">\n"); switch (def->type) { case VIR_INTERFACE_TYPE_ETHERNET: virInterfaceStartmodeDefFormat(buf, def->startmode, level); if (def->mac != NULL) virBufferAsprintf(buf, "%*s <mac address='%s'/>\n", level*2, "", def->mac); if (def->mtu != 0) virBufferAsprintf(buf, "%*s <mtu size='%d'/>\n", level*2, "", def->mtu); virInterfaceProtocolDefFormat(buf, def, level); break; case VIR_INTERFACE_TYPE_BRIDGE: virInterfaceStartmodeDefFormat(buf, def->startmode, level); if (def->mtu != 0) virBufferAsprintf(buf, "%*s <mtu size='%d'/>\n", level*2, "", def->mtu); virInterfaceProtocolDefFormat(buf, def, level); virInterfaceBridgeDefFormat(buf, def, level); break; case VIR_INTERFACE_TYPE_BOND: virInterfaceStartmodeDefFormat(buf, def->startmode, level); if (def->mtu != 0) virBufferAsprintf(buf, "%*s <mtu size='%d'/>\n", level*2, "", def->mtu); virInterfaceProtocolDefFormat(buf, def, level); virInterfaceBondDefFormat(buf, def, level); break; case VIR_INTERFACE_TYPE_VLAN: virInterfaceStartmodeDefFormat(buf, def->startmode, level); if (def->mac != NULL) virBufferAsprintf(buf, "%*s <mac address='%s'/>\n", level*2, "", def->mac); if (def->mtu != 0) virBufferAsprintf(buf, "%*s <mtu size='%d'/>\n", level*2, "", def->mtu); virInterfaceProtocolDefFormat(buf, def, level); virInterfaceVlanDefFormat(buf, def, level); break; } virBufferAsprintf(buf, "%*s</interface>\n", level*2, ""); if (virBufferError(buf)) goto no_memory; return 0; no_memory: virReportOOMError(); cleanup: return -1; }