Index: libvirt-0.7.4/src/conf/network_conf.c =================================================================== --- libvirt-0.7.4.orig/src/conf/network_conf.c +++ libvirt-0.7.4/src/conf/network_conf.c @@ -865,6 +865,137 @@ error: return NULL; } +static int virNetworkIsBridge(const char *name) +{ + char *path = NULL; + int ret = 0; + struct stat s; + + if (asprintf(&path, "/sys/class/net/%s/bridge", name) < 0) + goto out; + + if (stat(path, &s) != 0) + goto out; + + if (S_ISDIR(s.st_mode)) + ret = 1; + + out: + free(path); + return ret; +} + +static unsigned long virNetworkDefSuseGetValue(const char *netName, const char *valName) +{ + unsigned long ret = 0; + char *path = NULL; + FILE *f; + + if (asprintf(&path, "/sys/class/net/%s/bridge/%s", netName, valName) < 0) + return ret; + + if ((f = fopen(path, "r")) == NULL) + goto out; + + if (fscanf(f, "%lu", &ret) != 1) { + ret = 0; + goto out; + } + + + out: + if (f != NULL) + fclose(f); + free(path); + return ret; +} + +static virNetworkObjPtr virNetworkLoadSuseNet(virConnectPtr conn, + virNetworkObjListPtr nets, + const char *name) +{ + virNetworkDefPtr def; + virNetworkObjPtr network; + int err; + + if ((network = virNetworkFindByName(nets, name))) { + return network; + } + + if (VIR_ALLOC(network) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + return NULL; + } + + network->autostart = 1; + network->active = 1; + network->readonly = 1; + + if (VIR_ALLOC(def) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + + network->def = def; + + /* name */ + def->name = strdup(name); + if (def->name == NULL) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + + /* uuid */ + if ((err = virUUIDGenerate(def->uuid))) { + virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to generate UUID: %s"), strerror(err)); + goto error; + } + + /* bridge information */ + def->bridge = strdup(name); + if (def->bridge == NULL) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + goto error; + } + def->stp = (int)virNetworkDefSuseGetValue(name, "stp_state"); + def->delay = virNetworkDefSuseGetValue(name, "forward_delay"); + + /* Add network to the list */ + if (VIR_REALLOC_N(nets->objs, nets->count + 1) < 0) { + virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); + VIR_FREE(network); + return NULL; + } + + nets->objs[nets->count] = network; + nets->count++; + + return network; + + error: + virNetworkObjFree(network); + return NULL; +} + +static void virNetworkLoadSuseNetworks(virConnectPtr conn, + virNetworkObjListPtr nets) +{ + DIR *dir = NULL; + struct dirent *de; + + dir = opendir("/sys/class/net"); + if (dir == NULL) + return; + + while ((de = readdir(dir))) { + if (virNetworkIsBridge(de->d_name)) { + virNetworkLoadSuseNet(conn, nets, de->d_name); + } + } + closedir(dir); +} + int virNetworkLoadAllConfigs(virConnectPtr conn, virNetworkObjListPtr nets, const char *configDir, @@ -904,6 +1035,7 @@ int virNetworkLoadAllConfigs(virConnectP closedir(dir); + virNetworkLoadSuseNetworks(conn, nets); return 0; } Index: libvirt-0.7.4/src/conf/network_conf.h =================================================================== --- libvirt-0.7.4.orig/src/conf/network_conf.h +++ libvirt-0.7.4/src/conf/network_conf.h @@ -94,6 +94,7 @@ struct _virNetworkObj { unsigned int active : 1; unsigned int autostart : 1; unsigned int persistent : 1; + unsigned int readonly : 1; virNetworkDefPtr def; /* The current definition */ virNetworkDefPtr newDef; /* New definition to activate at shutdown */ Index: libvirt-0.7.4/src/network/bridge_driver.c =================================================================== --- libvirt-0.7.4.orig/src/network/bridge_driver.c +++ libvirt-0.7.4/src/network/bridge_driver.c @@ -994,6 +994,11 @@ static int networkShutdownNetworkDaemon( unlink(stateFile); VIR_FREE(stateFile); + if (network->readonly) { + VIR_WARN("Network '%s' is readonly\n", network->def->name); + return -1; + } + if (network->dnsmasqPid > 0) kill(network->dnsmasqPid, SIGTERM); @@ -1494,6 +1499,12 @@ static int networkSetAutostart(virNetwor goto cleanup; } + if (network->readonly) { + networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, + ": Network '%s' is readonly", network->def->name); + return -1; + } + autostart = (autostart != 0); if (network->autostart != autostart) {