static int testCompareXMLToXMLFiles(const char *xml) { char *xmlData = NULL; char *actual = NULL; int ret = -1; virInterfaceDefPtr dev = NULL; if (virtTestLoadFile(xml, &xmlData) < 0) goto fail; if (!(dev = virInterfaceDefParseString(xmlData))) goto fail; if (!(actual = virInterfaceDefFormat(dev))) goto fail; if (STRNEQ(xmlData, actual)) { virtTestDifferenceFull(stderr, xmlData, xml, actual, NULL); goto fail; } ret = 0; fail: VIR_FREE(xmlData); VIR_FREE(actual); virInterfaceDefFree(dev); return ret; }
virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces, virInterfaceDefPtr def) { virInterfaceObjPtr iface; if ((iface = virInterfaceFindByName(interfaces, def->name))) { virInterfaceDefFree(iface->def); iface->def = def; return iface; } if (VIR_ALLOC(iface) < 0) return NULL; if (virMutexInit(&iface->lock) < 0) { virReportError(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) { VIR_FREE(iface); return NULL; } interfaces->objs[interfaces->count] = iface; interfaces->count++; return iface; }
static virInterfacePtr udevInterfaceLookupByName(virConnectPtr conn, const char *name) { struct udev_iface_driver *driverState = conn->interfacePrivateData; struct udev *udev = udev_ref(driverState->udev); struct udev_device *dev; virInterfacePtr ret = NULL; virInterfaceDefPtr def = NULL; /* get a device reference based on the device name */ dev = udev_device_new_from_subsystem_sysname(udev, "net", name); if (!dev) { virReportError(VIR_ERR_NO_INTERFACE, _("couldn't find interface named '%s'"), name); goto cleanup; } if (!(def = udevGetMinimalDefForDevice(dev))) goto cleanup; if (virInterfaceLookupByNameEnsureACL(conn, def) < 0) goto cleanup; ret = virGetInterface(conn, def->name, def->mac); udev_device_unref(dev); cleanup: udev_unref(udev); virInterfaceDefFree(def); return ret; }
static void virInterfaceObjDispose(void *opaque) { virInterfaceObjPtr obj = opaque; virInterfaceDefFree(obj->def); }
void virInterfaceObjFree(virInterfaceObjPtr iface) { if (!iface) return; virInterfaceDefFree(iface->def); virMutexDestroy(&iface->lock); VIR_FREE(iface); }
void virInterfaceDefFree(virInterfaceDefPtr def) { size_t i; int pp; if (def == NULL) return; VIR_FREE(def->name); VIR_FREE(def->mac); switch (def->type) { case VIR_INTERFACE_TYPE_BRIDGE: VIR_FREE(def->data.bridge.delay); for (i = 0; i < def->data.bridge.nbItf; i++) { if (def->data.bridge.itf[i] == NULL) break; /* to cope with half parsed data on errors */ virInterfaceDefFree(def->data.bridge.itf[i]); } 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) break; /* to cope with half parsed data on errors */ virInterfaceDefFree(def->data.bond.itf[i]); } 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; } /* free all protos */ for (pp = 0; pp < def->nprotos; pp++) { virInterfaceProtocolDefFree(def->protos[pp]); } VIR_FREE(def->protos); VIR_FREE(def); }
static int udevNumOfInterfacesByStatus(virConnectPtr conn, virUdevStatus status, virInterfaceObjListFilter filter) { struct udev_iface_driver *driverState = conn->interfacePrivateData; struct udev *udev = udev_ref(driverState->udev); struct udev_enumerate *enumerate = NULL; struct udev_list_entry *devices; struct udev_list_entry *dev_entry; int count = 0; enumerate = udevGetDevices(udev, status); if (!enumerate) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to get number of %s interfaces on host"), virUdevStatusString(status)); count = -1; goto cleanup; } /* Do the scan to load up the enumeration */ udev_enumerate_scan_devices(enumerate); /* Get a list we can walk */ devices = udev_enumerate_get_list_entry(enumerate); /* For each item so we can count */ udev_list_entry_foreach(dev_entry, devices) { struct udev_device *dev; const char *path; virInterfaceDefPtr def; path = udev_list_entry_get_name(dev_entry); dev = udev_device_new_from_syspath(udev, path); def = udevGetMinimalDefForDevice(dev); if (filter(conn, def)) count++; udev_device_unref(dev); virInterfaceDefFree(def); } cleanup: if (enumerate) udev_enumerate_unref(enumerate); udev_unref(udev); return count; }
udevGetMinimalDefForDevice(struct udev_device *dev) { virInterfaceDef *def; /* Allocate our interface definition structure */ if (VIR_ALLOC(def) < 0) return NULL; if (VIR_STRDUP(def->name, udev_device_get_sysname(dev)) < 0) goto cleanup; if (VIR_STRDUP(def->mac, udev_device_get_sysattr_value(dev, "address")) < 0) goto cleanup; return def; cleanup: virInterfaceDefFree(def); return NULL; }
static virInterfacePtr udevInterfaceLookupByMACString(virConnectPtr conn, const char *macstr) { struct udev_iface_driver *driverState = conn->interfacePrivateData; struct udev *udev = udev_ref(driverState->udev); struct udev_enumerate *enumerate = NULL; struct udev_list_entry *dev_entry; struct udev_device *dev; virInterfaceDefPtr def = NULL; virInterfacePtr ret = NULL; enumerate = udevGetDevices(udev, VIR_UDEV_IFACE_ALL); if (!enumerate) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to lookup interface with MAC address '%s'"), macstr); goto cleanup; } /* Match on MAC */ udev_enumerate_add_match_sysattr(enumerate, "address", macstr); /* Do the scan to load up the enumeration */ udev_enumerate_scan_devices(enumerate); /* Get a list we can walk */ dev_entry = udev_enumerate_get_list_entry(enumerate); /* Check that we got something back */ if (!dev_entry) { virReportError(VIR_ERR_NO_INTERFACE, _("couldn't find interface with MAC address '%s'"), macstr); goto cleanup; } /* Check that we didn't get multiple items back */ if (udev_list_entry_get_next(dev_entry)) { virReportError(VIR_ERR_MULTIPLE_INTERFACES, _("the MAC address '%s' matches multiple interfaces"), macstr); goto cleanup; } dev = udev_device_new_from_syspath(udev, udev_list_entry_get_name(dev_entry)); if (!(def = udevGetMinimalDefForDevice(dev))) goto cleanup; if (virInterfaceLookupByMACStringEnsureACL(conn, def) < 0) goto cleanup; ret = virGetInterface(conn, def->name, def->mac); udev_device_unref(dev); cleanup: if (enumerate) udev_enumerate_unref(enumerate); udev_unref(udev); virInterfaceDefFree(def); return ret; }
static int udevConnectListAllInterfaces(virConnectPtr conn, virInterfacePtr **ifaces, unsigned int flags) { struct udev_iface_driver *driverState = conn->interfacePrivateData; struct udev *udev; struct udev_enumerate *enumerate = NULL; struct udev_list_entry *devices; struct udev_list_entry *dev_entry; virInterfacePtr *ifaces_list = NULL; virInterfacePtr iface_obj; int tmp_count; int count = 0; int status = 0; int ret; virCheckFlags(VIR_CONNECT_LIST_INTERFACES_FILTERS_ACTIVE, -1); if (virConnectListAllInterfacesEnsureACL(conn) < 0) return -1; /* Grab a udev reference */ udev = udev_ref(driverState->udev); /* List all interfaces in case we support more filter flags in the future */ enumerate = udevGetDevices(udev, VIR_UDEV_IFACE_ALL); if (!enumerate) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to get list of %s interfaces on host"), virUdevStatusString(status)); ret = -1; goto cleanup; } /* Do the scan to load up the enumeration */ udev_enumerate_scan_devices(enumerate); /* Get a list we can walk */ devices = udev_enumerate_get_list_entry(enumerate); /* For each item so we can count */ udev_list_entry_foreach(dev_entry, devices) { count++; } /* If we've got nothing, exit out */ if (count == 0) { ret = 0; goto cleanup; } /* If we're asked for the ifaces then alloc up memory */ if (ifaces && VIR_ALLOC_N(ifaces_list, count + 1) < 0) { ret = -1; goto cleanup; } /* Get a list we can walk */ devices = udev_enumerate_get_list_entry(enumerate); /* reset our iterator */ count = 0; /* Walk through each device */ udev_list_entry_foreach(dev_entry, devices) { struct udev_device *dev; const char *path; const char *name; const char *macaddr; virInterfaceDefPtr def; path = udev_list_entry_get_name(dev_entry); dev = udev_device_new_from_syspath(udev, path); name = udev_device_get_sysname(dev); macaddr = udev_device_get_sysattr_value(dev, "address"); status = STREQ(udev_device_get_sysattr_value(dev, "operstate"), "up"); def = udevGetMinimalDefForDevice(dev); if (!virConnectListAllInterfacesCheckACL(conn, def)) { udev_device_unref(dev); virInterfaceDefFree(def); continue; } virInterfaceDefFree(def); /* Filter the results */ if (MATCH(VIR_CONNECT_LIST_INTERFACES_FILTERS_ACTIVE) && !((MATCH(VIR_CONNECT_LIST_INTERFACES_ACTIVE) && status) || (MATCH(VIR_CONNECT_LIST_INTERFACES_INACTIVE) && !status))) { udev_device_unref(dev); continue; } /* If we matched a filter, then add it */ if (ifaces) { iface_obj = virGetInterface(conn, name, macaddr); ifaces_list[count++] = iface_obj; } udev_device_unref(dev); } /* Drop our refcounts */ udev_enumerate_unref(enumerate); udev_unref(udev); /* Trim the array to its final size */ if (ifaces) { ignore_value(VIR_REALLOC_N(ifaces_list, count + 1)); *ifaces = ifaces_list; ifaces_list = NULL; } return count; cleanup: if (enumerate) udev_enumerate_unref(enumerate); udev_unref(udev); if (ifaces) { for (tmp_count = 0; tmp_count < count; tmp_count++) virInterfaceFree(ifaces_list[tmp_count]); } VIR_FREE(ifaces_list); return ret; }
static int udevListInterfacesByStatus(virConnectPtr conn, char **const names, int names_len, virUdevStatus status, virInterfaceObjListFilter filter) { struct udev_iface_driver *driverState = conn->interfacePrivateData; struct udev *udev = udev_ref(driverState->udev); struct udev_enumerate *enumerate = NULL; struct udev_list_entry *devices; struct udev_list_entry *dev_entry; int count = 0; enumerate = udevGetDevices(udev, status); if (!enumerate) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to get list of %s interfaces on host"), virUdevStatusString(status)); goto error; } /* Do the scan to load up the enumeration */ udev_enumerate_scan_devices(enumerate); /* Get a list we can walk */ devices = udev_enumerate_get_list_entry(enumerate); /* For each item so we can count */ udev_list_entry_foreach(dev_entry, devices) { struct udev_device *dev; const char *path; virInterfaceDefPtr def; /* Ensure we won't exceed the size of our array */ if (count > names_len) break; path = udev_list_entry_get_name(dev_entry); dev = udev_device_new_from_syspath(udev, path); def = udevGetMinimalDefForDevice(dev); if (filter(conn, def)) { if (VIR_STRDUP(names[count], udev_device_get_sysname(dev)) < 0) { udev_device_unref(dev); virInterfaceDefFree(def); goto error; } count++; } udev_device_unref(dev); virInterfaceDefFree(def); } udev_enumerate_unref(enumerate); udev_unref(udev); return count; error: if (enumerate) udev_enumerate_unref(enumerate); udev_unref(udev); for (names_len = 0; names_len < count; names_len++) VIR_FREE(names[names_len]); return -1; }
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; }